mongo $slice 查询反向索引超出范围 [英] mongo $slice query reverse index out of range
问题描述
mongo 中的以下查询,表现得很奇怪:
db.items.findOne({},{ "List": { "$slice": [ skip, 3 ] }})
首先:它不是只返回一个带有 ["_id","List"] 键的对象,而是返回一个完整的对象.
第二:如果 skip
为负并且 |skip|
大于 list.length 那么它返回前三个元素,就像 skip==0
>
我希望:
<代码>{"_id" : ObjectId("542babf265f5de9a0d5c2928"),列表" : [1、2、3、4、5]其他":not_important"}
查询:
db.items.findOne({},{ "List": { "$slice": [-10, 3 ] }})
获得:
<代码>{"_id" : ObjectId("542babf265f5de9a0d5c2928"),列表" : []}
相反,我得到:
<代码>{"_id" : ObjectId("542babf265f5de9a0d5c2928"),列表" : [1、2、3]其他":not_important"}
为什么?
我使用 mongoDB 2.4.10
第二:如果skip为负且|skip|高于 list.length 则它返回前三个元素,就像 skip==0
是的.这就是 mongodb 内部使用的 javascript Array.prototype.slice()
方法的工作原理.
根据 ECMAScript® 语言规范,
<块引用>如果relativeStart为负数,令k为max((len + relativeStart),0);否则让 k 为 min(relativeStart, len).
在你的情况下 relativeStart 是 -10
,k = max((-10+5),0), k = 0;
(其中,5
是数组的长度).
因此,在这些情况下,k
或 skip
将始终为 0
.
第一:它返回一个完整的对象,而不是只返回一个带有 ["_id","List"] 键的对象.
是的,投影算子就是这样工作的.除非在投影参数中明确指定了inclusion
或exclusion
,否则整个文档将使用$slice
、$elemmatch
正在应用.
db.items.findOne({},{"_id":1,"List": { "$slice": [-10, 3 ] }})
会回来:
{ "_id" : ObjectId("542babf265f5de9a0d5c2928"), "List" : [ 1, 2, 3 ] }
findOne()
方法的第二个参数不仅用于简单投影
的目的,字段不投影,仅当有任何一个时field
名称的值对它们来说是 0
或 1
.如果不是,则返回整个文档.如果任何字段有要应用的 projection operator
,它将被 applied
和 projected
.
每当涉及 $slice
操作符时,投影机制似乎以下面的方式发生.
- 默认情况下,所有字段都将包含在投影中.
- 默认情况下,其值基于投影运算符
$slice
、if truthy 派生的所有字段始终显示,与以下无关.
为排除或纳入而采取的步骤.
- projection 参数中指定的字段列表按其指定的顺序累积.
- 仅针对遇到的值为0"或1"的第一个字段:如果字段的值为0" - 然后将其排除,其余所有字段被标记为包括在内.如果一个字段有 '1' - 那么它被包括在内,所有剩余的字段标记为排除.
- 对于所有后续字段,根据他们的价值观.
The following query in mongo, behaves strange :
db.items.findOne({},{ "List": { "$slice": [ skip, 3 ] }})
First: Instead of returning one object with ["_id","List"] keys only, it returns a full object.
Second:
if skip
is negative and |skip|
is higher than list.length then it returns the first three elements as though skip==0
I would expect for:
{
"_id" : ObjectId("542babf265f5de9a0d5c2928"),
"List" : [
1,
2,
3,
4,
5
]
"other" : "not_important"
}
query:
db.items.findOne({},{ "List": { "$slice": [-10, 3 ] }})
to get:
{
"_id" : ObjectId("542babf265f5de9a0d5c2928"),
"List" : []
}
instead, I get:
{
"_id" : ObjectId("542babf265f5de9a0d5c2928"),
"List" : [
1,
2,
3
]
"other" : "not_important"
}
Why?
I use mongoDB 2.4.10
Second: if skip is negative and |skip| is higher than list.length then it returns the first three elements as though skip==0
Yes. That is how the javascript Array.prototype.slice()
method works, which is internally used by mongodb.
According to the ECMAScript® Language Specification,
If relativeStart is negative, let k be max((len + relativeStart),0); else let k be min(relativeStart, len).
In your case relativeStart is -10
,
k = max((-10+5),0), k = 0;
(where, 5
is the length of your array).
Hence k
or skip
will always be 0
, in these cases.
First: Instead of returning one object with ["_id","List"] keys only, it returns a full object.
Yes, the projection operator works that way. Unless a inclusion
or exclusion
is explicitly specified in the projection parameter, the whole document is retrieved with the projection operators such as $slice
,$elemmatch
being applied.
db.items.findOne({},{"_id":1,"List": { "$slice": [-10, 3 ] }})
would return:
{ "_id" : ObjectId("542babf265f5de9a0d5c2928"), "List" : [ 1, 2, 3 ] }
The second parameter to the findOne()
method is not only for simple projection
purpose, fields are not projected, only if any one of the field
names have a value of 0
or 1
against them. If not the whole document is returned. If any field has a projection operator
to be applied, it would be applied
and projected
.
The projection mechanism seems to happen in the below manner, whenever the $slice
operator is involved.
- By default all the fields would be included for projection.
- By Default all the fields whose values are derived based on the projection operator,
$slice
, if truthy, are always displayed, irrespective of the below.
Steps taking place for exclusion or inclusion.
- The list of fields specified in the projection parameter are accumulated in their specified order.
- For only the first field encountered with value '0' or '1': If the field has a value '0' - then it is excluded, and all the remaining fields are marked to be included. If a field has '1' - then it is included, and all the remaining fields are marked to be excluded.
- For all the subsequent fields, they are excluded or included based on their values.
这篇关于mongo $slice 查询反向索引超出范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!