如何在MongoDB单个集合中查找文档之间集合交集?

7
下面的集合名为“coll”,它在MongoDB中被维护。
{
    {"_id":1, "set":[1,2,3,4,5]},
    {"_id":2, "set":[0,2,6,4,5]},
    {"_id":3, "set":[1,2,5,10,22]}
}

如何找到上述文档集合中与_id为1和3的元素的交集。
1个回答

10
使用聚合框架来获得所需结果。实现这一魔法的聚合集合运算符$setIntersection
以下聚合管道实现了您想要的结果:
db.test.aggregate([
    {
        "$match": {
            "_id": { "$in": [1, 3] }
        }
    },
    {
        "$group": {
            "_id": 0,
            "set1": { "$first": "$set" },
            "set2": { "$last": "$set" }
        }
    },
    {
        "$project": { 
            "set1": 1, 
            "set2": 1, 
            "commonToBoth": { "$setIntersection": [ "$set1", "$set2" ] }, 
            "_id": 0 
        }
    }
])

输出:

/* 0 */
{
    "result" : [ 
        {
            "set1" : [1,2,3,4,5],
            "set2" : [1,2,5,10,22],
            "commonToBoth" : [1,2,5]
        }
    ],
    "ok" : 1
}

更新

如果要相交三个或更多文档,则需要使用$reduce操作符来展平数组。这将允许你相交任意数量的数组,因此不仅可以对来自文档1和3的两个数组进行相交,还可以应用于多个数组。

考虑运行以下聚合操作:

db.test.aggregate([
    { "$match": { "_id": { "$in": [1, 3] } } },
    {
        "$group": {
            "_id": 0,
            "sets": { "$push": "$set" },
            "initialSet": { "$first": "$set" }
        }
    },
    {
        "$project": {
            "commonSets": {
                "$reduce": {
                    "input": "$sets",
                    "initialValue": "$initialSet",
                    "in": { "$setIntersection": ["$$value", "$$this"] }
                }
            }
        }
    }
])

1
你能解释一下管道的组阶段正在发生什么以及如果我们想在集合中执行三个或四个文档的交集,该如何继续吗? - kane.zorfy
1
只有当要求交集的文档恰好为两个时,此方法才有效。如果有三个或更多文档,则无法使用 $first 和 $last 分别投影数组(因为它们不再适用)。 - Vince Bowdren
恭喜您的回复!但我有以下问题:由于我想要求交集,所以当我的集合非常大时,我会得到BufBuilder attempted to grow() to 67108870 bytes, past the 64MB limit.的错误提示:每个集合可能包含约600K个7字节元素。您有什么解决方案或变通方法吗?提前感谢您! - mspapant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接