mongo中的以下查询表现得很奇怪:
db.items.findOne({},{ "List": { "$slice": [ skip, 3 ] }})
第一:
,它不是仅使用[“_id”,“List”]键返回一个对象,而是返回一个完整的对象。第二:
如果skip
为负且|skip|
高于list.length,则返回前三个元素,就像skip==0
我希望:
{
"_id" : ObjectId("542babf265f5de9a0d5c2928"),
"List" : [
1,
2,
3,
4,
5
]
"other" : "not_important"
}
查询:
db.items.findOne({},{ "List": { "$slice": [-10, 3 ] }})
得到:
{
"_id" : ObjectId("542babf265f5de9a0d5c2928"),
"List" : []
}
相反,我得到:
{
"_id" : ObjectId("542babf265f5de9a0d5c2928"),
"List" : [
1,
2,
3
]
"other" : "not_important"
}
为什么?
我使用mongoDB 2.4.10
答案 0 :(得分:4)
第二:如果skip为负且| skip |高于list.length然后返回前三个元素,就像skip == 0
一样
是。这就是javascript Array.prototype.slice()
方法的工作原理,mongodb在内部使用它。
根据ECMAScript® Language Specification,
如果relativeStart为负数,则k为max((len + relativeStart),0); 否则让k为min(relativeStart,len)。
在您的案例中relativeStart is -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()
方法的第二个参数是not only for simple projection
目的,字段不投影,仅当field
个名称中的任何一个具有值0
或1
反对他们。如果不是,则返回整个文档。如果任何字段要应用projection operator
,则为applied
和projected
。
当涉及$slice
运算符时,投影机制似乎以下面的方式发生。
$slice
, if truthy 得出的所有字段。答案 1 :(得分:1)
虽然这种行为是设计用于$slice
运算符,但是由于MongoDB 3.2可以对此进行评估并使用$slice
的聚合运算符更改结果:
给出示例文档:
Object.extend = function (source, extension) {
var hasOwnProperty = Object.hasOwnProperty;
var object = Object.create(source);
for (var property in extension)
if (hasOwnProperty.call(extension, property) ||
typeof object[property] === "undefined")
object[property] = extension[property];
return object;
};
var rectangle = {
create: function (width, height) {
var self = {
width: width,
height: height,
area: function () {
return self.width * self.height;
}
};
return self;
}
};
var square = Object.extend(rectangle, {
create: function (side) {
return rectangle.create(side, side);
}
});
var sq = square.create(5);
console.log(sq.area());
如果给出条件表达式来测试具有$size
的数组的长度,并且只在反向索引大于或等于该长度时执行$slice
,否则返回一个空数组:
{ "_id" : ObjectId("5922846dbcf60428d0f69f6e"), "a" : [ 1, 2, 3, 4 ] }
{ "_id" : ObjectId("5922847cbcf60428d0f69f6f"), "a" : [ 5, 6 ] }
然后你得到:
db.collection.aggregate([
{ "$project": {
"a": {
"$cond": {
"if": { "$gte": [ { "$size": "$a" }, 4 ] },
"then": { "$slice": [ "$a", -4, 2 ] },
"else": { "$literal": [] },
}
}
}}
])
这就是为什么你可以让MongoDB返回一个以这种方式起作用的“切片”。