mongodb查询查找数组中的对象与另一个数组字段的元素不匹配的位置

我收集了如下文件:

{
_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作为可以进行此比较的两个工具.

点赞