$slice (投影)
定义
$slice
的
$slice
投影运算符指定查询结果中返回的数组元素数量。
语法
$slice
具有以下语法形式之一
db.collection.find( <query>, { <arrayField>: { $slice: <number> } } );
或
db.collection.find( <query>, { <arrayField>: { $slice: [ <number>, <number> ] } } );
值 | 描述 |
---|---|
$slice: <number> | 指定在
如果 |
$slice: [ <number to skip>, <number to return> ] | 指定在跳过从第一个元素开始的指定数量元素后,在 对于
对于 |
行为
$slice
of Embedded Array
嵌套文档中数组 $slice
投影在包含投影的一部分时不再返回嵌套文档中的其他字段。
例如,考虑一个包含 size
字段的 inventory
集合
{ item: "socks", qty: 100, details: { colors: [ "blue", "red" ], sizes: [ "S", "M", "L"] } }
以下操作投影 _id
字段(默认),qty
字段,以及仅指定切片的 details
字段,用于 colors
数组
db.inventory.find( { }, { qty: 1, "details.colors": { $slice: 1 } } )
即,操作返回以下文档
{ "_id" : ObjectId("5ee92a6ec644acb6d13eedb1"), "qty" : 100, "details" : { "colors" : [ "blue" ] } }
如果$slice
投影是排除投影的一部分,则操作将继续返回嵌套文档中的其他字段。也就是说,以下投影是一个排除投影。该投影排除了_id
字段和落在指定切片之外的颜色数组的元素,并返回所有其他字段。
db.inventory.find( { }, { _id: 0, "details.colors": { $slice: 1 } } )
{ "item" : "socks", "qty" : 100, "details" : { "colors" : [ "blue" ], "sizes" : [ "S", "M", "L" ] } }
仅$slice
投影本身被视为排除。
在之前的版本中,$slice
投影也包含嵌套文档中的其他字段,无论投影是包含还是排除。
视图限制
在视图上执行的db.collection.find()
操作不支持$slice
投影运算符。
$
位置运算符和$slice
限制
find
和findAndModify
投影不能将$slice
投影表达式作为$
投影表达式的一部分。
例如,以下操作是无效的
db.inventory.find( { "instock.qty": { $gt: 25 } }, { "instock.$": { $slice: 1 } } )
在之前的版本中,MongoDB 返回匹配查询条件的 instock
数组中的第一个元素(instock.$
);即位置投影 "instock.$"
优先级更高,而 $slice:1
是一个空操作。表达式 "instock.$": { $slice: 1 }
不会排除任何其他文档字段。
路径冲突:数组的 $slice
和嵌套字段
find
和 findAndModify
投影不能同时包含数组的一个 $slice
和数组中嵌入的字段。
例如,考虑一个包含数组字段 instock
的集合 inventory
。
{ ..., instock: [ { warehouse: "A", qty: 35 }, { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ], ... }
以下操作由于 Path collision
错误而失败
db.inventory.find( {}, { "instock": { $slice: 1 }, "instock.warehouse": 0 } )
在之前的版本中,投影同时应用两个投影并返回 instock
数组中的第一个元素($slice: 1
),但抑制了投影元素中的 warehouse
字段。从 MongoDB 4.4 版本开始,为了达到相同的结果,请使用 db.collection.aggregate()
方法并包含两个独立的 $project
阶段。
示例
创建一个包含以下文档的示例集合 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" } ] } ])
返回包含前三个元素的数组
以下操作使用$slice
投影运算符在comments
数组上,以返回包含前三个元素的数组。如果数组元素少于三个,则返回数组中所有元素。
db.posts.find( {}, { comments: { $slice: 3 } } )
此操作返回以下文档
{ "_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" } ] }
返回包含最后三个元素的数组
以下操作使用$slice
投影运算符在comments
数组上,以返回包含最后三个元素的数组。如果数组元素少于三个,则返回数组中所有元素。
db.posts.find( {}, { comments: { $slice: -3 } } )
此操作返回以下文档
{ "_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" } ] }
跳过第一个元素后返回包含3个元素的数组
以下操作使用$slice
投影运算符对comments
数组进行处理,
跳过第一个元素,使得第二个元素为起点。
然后,从起点返回三个元素。
如果跳过后数组中元素少于三个,则返回所有剩余元素。
db.posts.find( {}, { comments: { $slice: [ 1, 3 ] } } )
此操作返回以下文档
{ "_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" } ] }
跳过最后一个元素后返回包含3个元素的数组
以下操作使用$slice
投影运算符对comments
数组进行处理,
从第一个元素开始向后跳过,使得最后一个元素为起点。
然后,从起点返回三个元素。
如果跳过后数组中元素少于三个,则返回数组中的所有剩余元素。
db.posts.find( {}, { comments: { $slice: [ -1, 3 ] } } )
此操作返回以下文档
{ "_id" : 1, "title" : "Bagels are not croissants.", "comments" : [ { "comment" : "1. croissants aren't bagels." } ] } { "_id" : 2, "title" : "Coffee please.", "comments" : [ { "comment" : "4. whatever" } ] }