查询mongodb记录,将数组中的值与查询中传递的数组进行比较

时间:2016-10-13 19:10:09

标签: mongodb mongodb-query aggregation-framework

我有一份格式为

的文件
{
"history": [
{
  "plugin": [
    1,
    2,
    3,
    4
  ]
},
{
  "plugin": [
    2,
    3,
    4,
    6
  ]
},
{
  "plugin": [
    1,
    4
  ]
}
]
}

我有一个数组x = [2,7],

我希望以这样的方式进行查询:如果x中至少有一个与插件数组中的任何元素匹配的元素,则应该返回

因此对于这种情况,预期结果是

{
"history": [
{
  "plugin": [
    1,
    2,
    3,
    4
  ]
},
{
  "plugin": [
    2,
    3,
    4,
    6
  ]
}    
]
}

1 个答案:

答案 0 :(得分:1)

运行以下管道,该管道使用 $filter 运算符返回传递给定指定条件的history数组的子集。此条件使用 $setIntersection 集合运算符检查嵌入的plugin数组是否与给定的输入比较数组相交。

例如,表达式

{ $setIntersection: [ [ 1, 4 ],  [ 2, 7 ] ] }   

将返回一个空集(数组[]),因为两个数组不相交。使用此作为基础,将结果与 $ne 比较运算符进行比较。当比较的两个值不相等时,这将返回true,当它们相等时,将返回false。使用此结果提供“cond”表达式,以便过滤相应的元素。

以下管道演示了这一点:

var arr = [2,7];
db.collection.aggregate([
    { "$match": { "_id": ObjectId("57ffe28591f567293497d924") } },  // <-- filter here      
    {
        "$project": {
            "history": {
                "$filter": {
                    "input": "$history",
                    "as": "item",
                    "cond": {
                        "$ne": [
                            { "$setIntersection": ["$$item.plugin", arr] },
                            []
                        ]
                    }
                }
            }
        }
    }
])

示例输出

{
    "_id" : ObjectId("57ffe28591f567293497d924"),
    "history" : [ 
        {
            "plugin" : [ 
                1, 
                2, 
                3, 
                4
            ]
        }, 
        {
            "plugin" : [ 
                2, 
                3, 
                4, 
                6
            ]
        }
    ]
}

作为替代解决方案(如果您的MongoDB版本不支持 $filter 运算符),请考虑使用 $setDifference 的组合, $map 运算符返回已过滤的数组:

var arr = [2,7];
db.collection.aggregate([
    { "$match": { "_id": ObjectId("57ffe28591f567293497d924") } },  // <-- filter here      
    {
        "$project": {
            "history": {
                 "$setDifference": [
                    {
                        "$map": {
                            "input": "$history",
                            "as": "item",
                            "in": {
                                "$cond": [
                                    {
                                        "$ne": [
                                            { "$setIntersection": ["$$item.plugin", arr] },
                                            []
                                        ]
                                    },
                                    "$$item",
                                    false
                                ]
                            }
                        }
                    },
                    [false]
                 ]
            }
        }
    }
])