MongoDB $slice

In MongoDB, the $slice aggregation pipeline operator returns a subset of an array.

To use $slice, you specify the number of elements to return from the array. You can also specify a starting position for which to take the subset from the array.

Example

Suppose we have a collection called test with the following document:

{ "_id" : 1, "data" : [ "Aardvark", "Buffalo", "Cat", "Dog", "Horse", "Gorilla", "Zebra" ] }

We can use $slice to take a subset from the array in the data field.

Positive Integer

Providing a single positive value determines the starting position from the start of the array.

db.test.aggregate(
   [
     {
       $project:
          {
            _id: 0,
            result: { $slice: [ "$data", 3 ] }
          }
     }
   ]
)

Result:

{ "result" : [ "Aardvark", "Buffalo", "Cat" ] }

In this case, we provided a positive number of 3, and so the first three elements where returned from the array.

Negative Integer

Providing a single negative value determines the starting position from the end of the array.

db.test.aggregate(
   [
     {
       $project:
          {
            _id: 0,
            result: { $slice: [ "$data", -3 ] }
          }
     }
   ]
)

Result:

{ "result" : [ "Horse", "Gorilla", "Zebra" ] }

In this case we returned the last three elements from the array.

Note that you can’t specify a negative integer when you also specify a starting position. More on this later.

Specify a Starting Position

You also have the option of specifying a starting position. To do this, provide another integer before the other one.

Positive Integer

Here’s an example of using a positive integer for the starting position:

db.test.aggregate(
   [
     {
       $project:
          {
            _id: 0,
            result: { $slice: [ "$data", 2, 3 ] }
          }
     }
   ]
)

Result:

{ "result" : [ "Cat", "Dog", "Horse" ] }

In this case we specified a starting position of 2 and a slice size of 3.

Note that arrays are zero-based, and therefore our positive integer of 2 resulted in the slice operation starting at the third position.

Negative Integer

Here’s an example of using a negative integer for the starting position:

db.test.aggregate(
   [
     {
       $project:
          {
            _id: 0,
            result: { $slice: [ "$data", -4, 3 ] }
          }
     }
   ]
)

Result:

{ "result" : [ "Dog", "Horse", "Gorilla" ] }

In this case, we specified -4, which resulted in the slice operation counting back four places from the end.

Oversized Slices

Providing a slice size that’s larger than the available elements in the array results in just the remaining array elements being returned.

Example:

db.test.aggregate(
   [
     {
       $project:
          {
            _id: 0,
            result: { $slice: [ "$data", -1, 3 ] }
          }
     }
   ]
)

Result:

{ "result" : [ "Zebra" ] }

Here we specified that three elements should be returned, even though we only started one position back from the end of the array. In this case, just one element was returned (the last one in the array).

Out of Range Starting Position

Providing a starting position that’s out of the range of the array may return some elements or an empty array. It all depends on the values being provided.

Here’s an example that returns an empty array:

db.test.aggregate(
   [
     {
       $project:
          {
            _id: 0,
            result: { $slice: [ "$data", 10, 3 ] }
          }
     }
   ]
)

Result:

{ "result" : [ ] }

This returned an empty array because the starting position was 10, even though there are only 7 elements in the array (and the count would go from 0 to 6).

However, if we provide a negative value that’s greater than the array size, the slice starts from the start of the array.

Example:

db.test.aggregate(
   [
     {
       $project:
          {
            _id: 0,
            result: { $slice: [ "$data", -10, 3 ] }
          }
     }
   ]
)

Result:

{ "result" : [ "Aardvark", "Buffalo", "Cat" ] }

Negative Slice with a Starting Position

As mentioned, you can’t specify a negative integer when you also specify a starting position. Doing this results in an error.

Example:

db.test.aggregate(
   [
     {
       $project:
          {
            _id: 0,
            result: { $slice: [ "$data", 4, -3 ] }
          }
     }
   ]
)

Result:

Error: command failed: {
	"ok" : 0,
	"errmsg" : "Third argument to $slice must be positive: -3",
	"code" : 28729,
	"codeName" : "Location28729"
} : aggregate failed :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:18:14
_assertCommandWorked@src/mongo/shell/assert.js:639:17
assert.commandWorked@src/mongo/shell/assert.js:729:16
DB.prototype._runAggregate@src/mongo/shell/db.js:266:5
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1058:12
@(shell):1:1