mongo $slice 查询反向索引超出范围 [英] mongo $slice query reverse index out of range

查看:16
本文介绍了mongo $slice 查询反向索引超出范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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 是 -10k = max((-10+5),0), k = 0;(其中,5 是数组的长度).

因此,在这些情况下,kskip 将始终为 0.

<块引用>

第一:它返回一个完整的对象,而不是只返回一个带有 ["_id","List"] 键的对象.

是的,投影算子就是这样工作的.除非在投影参数中明确指定了inclusionexclusion,否则整个文档将使用$slice$elemmatch 正在应用.

db.items.findOne({},{"_id":1,"List": { "$slice": [-10, 3 ] }})

会回来:

{ "_id" : ObjectId("542babf265f5de9a0d5c2928"), "List" : [ 1, 2, 3 ] }

findOne() 方法的第二个参数不仅用于简单投影 的目的,字段投影,仅当有任何一个时field 名称的值对它们来说是 01.如果不是,则返回整个文档.如果任何字段有要应用的 projection operator,它将被 appliedprojected.

每当涉及 $slice 操作符时,投影机制似乎以下面的方式发生.

  • 默认情况下,所有字段都将包含在投影中.
  • 默认情况下,其值基于投影运算符 $sliceif 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆