Database Manual / Reference / Query Language / Projection

$slice (projection)(投影)

Definition定义

$slice

The $slice projection operator specifies the number of elements in an array to return in the query result.$slice投影运算符指定要在查询结果中返回的数组中的元素数。

Note

Disambiguation消歧

The $slice projection operator can only be used within a find command projection. $slice投影运算符只能在find命令投影中使用。To use $slice anywhere an expression can be used, see the $slice expression operator.要在任何可以使用表达式的地方使用$slice,请参阅$slice表达式运算符

For information on limiting the size of an array during an update with $push, see the $slice update modifier instead.有关在使用$push更新期间限制数组大小的信息,请参阅$slice更新修饰符

Syntax语法

The $slice has one of the following syntax forms:$slice具有以下语法形式之一:

db.collection.find(
<query>,
{ <arrayField>: { $slice: <number> } }
);

or

db.collection.find(
<query>,
{ <arrayField>: { $slice: [ <number>, <number> ] } }
);
ValueDescription描述
$slice: <number>

Specifies the number of elements to return in the <arrayField>. For <number>:指定要在<arrayField>中返回的元素数。对于<number>

  • Specify a positive number n to return the first n elements.指定一个正数n以返回前n个元素。
  • Specify a negative number n to return the last n elements.指定一个负数n以返回最后n个元素。

If the <number> is greater than the number of array elements, the query returns all array elements.如果<number>大于数组元素的数量,则查询将返回所有数组元素。

$slice: [ <number to skip>, <number to return> ]

Specifies the number of elements to return in the <arrayField> after skipping the specified number of elements starting from the first element. You must specify both elements.指定从第一个元素开始跳过指定数量的元素后,在<arrayField>中返回的元素数量。您必须同时指定这两个元素。

For the <number to skip>:对于<number to skip>

  • Specify a positive number n to skip n elements from the start of the array; i.e. 0th index position. 指定一个正数n以跳过数组开头的n个元素;即第0个索引位置。Based on a zero-based array index, 1 indicates the starting position of the 2nd element, etc. 基于从零开始的数组索引,1表示第二个元素的起始位置,以此类推。If n is greater than the number of array elements, the query returns an empty array for the <arrayField>.如果n大于数组元素的数量,则查询将为<arrayField>返回一个空数组。
  • Specify a negative number n to skip backward n elements from the start of the array; i.e. 0th index position Based on a zero-based array index (i.e. the first element is at index 0), -1 indicates the starting position of the last element, etc. If the absolute value of the negative number is greater than the number of array elements, the starting position is the start of the array.指定一个负数n,从数组开始向后跳过n个元素;即第0个索引位置基于从零开始的数组索引(即第一个元素位于索引0处),-1表示最后一个元素的起始位置,以此类推。如果负数的绝对值大于数组元素的数量,则起始位置是数组的开始。

For the <number to return>, you must specify a positive number n to return the next n elements, starting after skipping the specified number.对于<number to return>,您必须指定一个正数n来返回接下来的n个元素,从跳过指定的数字开始。

Behavior行为

$slice of Embedded Array嵌入式数组的$slice

The $slice projection of an array in an nested document no longer returns the other fields in the nested document when the projection is part of an inclusion projection.当投影是包含投影的一部分时,嵌套文档中数组的$slice投影不再返回嵌套文档中的其他字段。

For example, consider a collection inventory with documents that contain a size field:例如,考虑一个包含尺寸字段的文档的集合inventory

{ item: "socks", qty: 100, details: { colors: [ "blue", "red" ], sizes: [ "S", "M", "L"] } }

The following operation projects the _id field (by default), the qty field, and the details field with just the specified slice of the colors array:以下操作仅使用colors数组的指定分片投影_id字段(默认情况下)、qty字段和details字段:

db.inventory.find( { }, { qty: 1, "details.colors": { $slice: 1 } } )

That is, the operation returns the following document:也就是说,该操作返回以下文档:

{ "_id" : ObjectId("5ee92a6ec644acb6d13eedb1"), "qty" : 100, "details" : { "colors" : [ "blue" ] } }

If the $slice projection is part of an exclusion projection, the operation continues to return the other fields in the nested document. 如果$slice投影是排除投影的一部分,则操作将继续返回嵌套文档中的其他字段。That is, the following projection is an exclusion projection. The projection excludes the _id field and the elements in the colors array that fall outside the specified slice and returns all other fields.也就是说,以下投影是排除投影。投影排除_id字段和colors数组中位于指定分片之外的元素,并返回所有其他字段。

db.inventory.find( { }, { _id: 0, "details.colors": { $slice: 1 } } )
{ "item" : "socks", "qty" : 100, "details" : { "colors" : [ "blue" ], "sizes" : [ "S", "M", "L" ] } }

The $slice projection by itself is considered an exclusion.$slice投影本身被认为是一种排除。

In previous versions, the $slice projection also include the other fields in the nested document regardless of whether the projection is an inclusion or an exclusion.在以前的版本中,$slice投影还包括嵌套文档中的其他字段,无论投影是包含还是排除。

View Restriction查看限制

db.collection.find() operations on views do not support $slice projection operator.视图上的db.collection.find()操作不支持$slice投影运算符。

$ Positional Operator and $slice Restriction$位置运算符和$slice限制

find and findAndModify projection cannot include $slice projection expression as part of a $ projection expression.findfindAndModify投影不能将$slice投影表达式作为$投影表达式的一部分。

For example, the following operation is invalid:例如,以下操作无效:

db.inventory.find( { "instock.qty": { $gt: 25 } }, { "instock.$": { $slice: 1 } } )

In previous versions, MongoDB returns the first element (instock.$) in the instock array that matches the query condition; i.e. the positional projection "instock.$" takes precedence and the $slice:1 is a no-op. The "instock.$": { $slice: 1 } does not exclude any other document field.在以前的版本中,MongoDB返回instock数组中与查询条件匹配的第一个元素(instock.$);即,位置投影"instock.$"优先,$slice:1是无操作的。"instock.$": { $slice: 1 }不排除任何其他文档字段。

Path Collision: $slice of an Array and Embedded Fields路径冲突:数组和嵌入字段的$slice

find and findAndModify projection cannot contain both a $slice of an array and a field embedded in the array.findfindAndModify投影不能同时包含数组的$slice和数组中嵌入的字段。

For example, consider a collection inventory that contains an array field instock:例如,考虑一个包含instock数组字段的集合inventory

{ ..., instock: [ { warehouse: "A", qty: 35 }, { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ], ... }

The following operation fails with a Path collision error:以下操作失败,出现“路径冲突”错误:

db.inventory.find( {}, { "instock": { $slice: 1 }, "instock.warehouse": 0 } )

In previous versions, the projection applies both projections and returns the first element ($slice: 1) in the instock array but suppresses the warehouse field in the projected element. 在以前的版本中,投影应用了这两个投影,并返回instock数组中的第一个元素($slice:1),但抑制了投影元素中的warehouse字段。Starting in MongoDB 4.4, to achieve the same result, use the db.collection.aggregate() method with two separate $project stages.从MongoDB 4.4开始,要实现相同的结果,请使用db.collection.aggregate()方法和两个单独的$project阶段。

Examples示例

Create an example collection posts with the following documents:使用以下文档创建示例集合posts

db.posts.insertMany([
{
_id: 1,
title: "Bagels are not croissants.",
comments: [ { comment: "0. true" }, { comment: "1. croissants aren't bagels."} ]
},
{
_id: 2,
title: "Coffee please.",
comments: [ { comment: "0. fooey" }, { comment: "1. tea please" }, { comment: "2. iced coffee" }, { comment: "3. cappuccino" }, { comment: "4. whatever" } ]
}
])

Return an Array with Its First 3 Elements返回一个包含前3个元素的数组

The following operation uses the $slice projection operator on the comments array to return the array with its first three elements. If the array has less than three elements, all elements in the array are returned.以下操作使用注释数组上的$slice投影运算符返回包含前三个元素的数组。如果数组中的元素少于三个,则返回数组中的所有元素。

db.posts.find( {}, { comments: { $slice: 3 } } )

The operation returns the following documents:该操作返回以下文档:

{
"_id" : 1,
"title" : "Bagels are not croissants.",
"comments" : [ { "comment" : "0. true" }, { "comment" : "1. croissants aren't bagels." } ]
}
{
"_id" : 2,
"title" : "Coffee please.",
"comments" : [ { "comment" : "0. fooey" }, { "comment" : "1. tea please" }, { "comment" : "2. iced coffee" } ]
}

Return an Array with Its Last 3 Elements返回一个包含最后3个元素的数组

The following operation uses the $slice projection operator on the comments array to return the array with its last three elements. If the array has less than three elements, all elements in the array are returned.以下操作使用comments数组上的$slice投影运算符返回包含最后三个元素的数组。如果数组中的元素少于三个,则返回数组中的所有元素。

db.posts.find( {}, { comments: { $slice: -3 } } )

The operation returns the following documents:该操作返回以下文档:

{
"_id" : 1,
"title" : "Bagels are not croissants.",
"comments" : [ { "comment" : "0. true" }, { "comment" : "1. croissants aren't bagels." } ]
}
{
"_id" : 2,
"title" : "Coffee please.",
"comments" : [ { "comment" : "2. iced coffee" }, { "comment" : "3. cappuccino" }, { "comment" : "4. whatever" } ]
}

Return an Array with 3 Elements After Skipping the First Element跳过第一个元素后返回一个包含3个元素的数组

The following operation uses the $slice projection operator on the comments array to:以下操作在comments数组上使用$slice投影运算符:

  • Skip the first element such that the second element is the starting point.跳过第一个元素,使第二个元素成为起点。
  • Then, return three elements from the starting point.然后,从起点返回三个元素。

If the array has less than three elements after the skip, all remaining elements are returned.如果跳过后数组的元素少于三个,则返回所有剩余的元素。

db.posts.find( {}, { comments: { $slice: [ 1, 3 ] } } )

The operation returns the following documents:该操作返回以下文档:

{
"_id" : 1,
"title" : "Bagels are not croissants.",
"comments" : [ { "comment" : "1. croissants aren't bagels." } ]
}

{
"_id" : 2,
"title" : "Coffee please.",
"comments" : [ { "comment" : "1. tea please" }, { "comment" : "2. iced coffee" }, { "comment" : "3. cappuccino" } ]
}

Return an Array with 3 Elements After Skipping the Last Element跳过最后一个元素后返回一个包含3个元素的数组

The following operation uses the $slice projection operator on the comments array to以下操作在comments数组上使用$slice投影运算符

  • Skip backwards from the first element such that the last element is the starting point.从第一个元素向后跳,以最后一个元素为起点。
  • Then, return three elements from the starting point.然后,从起点返回三个元素。

If the array has less than three elements after the skip, all remaining elements in the array are returned.如果跳过后数组中的元素少于三个,则返回数组中所有剩余的元素。

db.posts.find( {}, { comments: { $slice: [ -1, 3 ] } } )

The operation returns the following documents:该操作返回以下文档:

{
"_id" : 1,
"title" : "Bagels are not croissants.",
"comments" : [ { "comment" : "1. croissants aren't bagels." } ]
}
{
"_id" : 2,
"title" : "Coffee please.",
"comments" : [ { "comment" : "4. whatever" } ]
}