我收集了如下文件:
{
_id: ObjectId("55b164c65c1a8f360078c917"),
message_id: ["abc","def"],
message: [{message_id: "efgh", message_body: "somebody"}]
}
我想找出mongodb查询来找出那些message.message_id不在message_id中的文档.
任何人都可以帮我这个.
最佳答案 MongoDB 2.6及更高版本的最佳方法可能是使用.aggregate()和
$redact
:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$gt": [
{ "$size": {
"$setIntersection": [
{ "$map": {
"input": "$message",
"as": "msg",
"in": "$$msg.message_id"
}},
"$message_id"
]
}},
0
]
},
"then": "$$PRUNE",
"else": "$$KEEP"
}
}}
])
这里逻辑的“由内而外”是$map
用于从“messages”数组中取出“message_id”的键,并将其返回以与“message_id”数组本身进行比较,以查看$setIntersection
的结果.这样做是为了看到“十字路口”,因为这里没有什么具体的东西说一个是另一个的“子集”.所以它只是常见元素,否则就有$setIsSubset.
当然,如果该交集的$size大于0,则存在元素匹配.因此,真正的条件将被“修剪”,其他任何东西都“被保留”.
或者在以前的版本中使用$where
而不是这个JavaScript eval,完全相同的逻辑:
db.collection.find({
"$where": function() {
var self = this;
return self.message.map(function(el) {
return el.message_id;
}).filter(function(el) {
return self.mesage_id.indexOf(el) != -1
}).length == 0;
}
})
在早期版本中也可以使用聚合管道,但是需要几个管道阶段,因此需要多次完成.因此,这不是MongoDB 2.6之前的最佳选择.
无论如何,标准查询操作通常不能“比较”文档的一个元素与另一个元素.因此,这将使聚合框架或$where作为可以进行此比较的两个工具.