Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find set intersection of sets between the documents in a single collection in MongoDB?

Tags:

mongodb

The below collection named "coll" was maintained in the 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]}
}

How to find the intersection of the set elements in the above collection documents with _id's 1 and 3.

like image 372
karthik.zorfy Avatar asked Jun 04 '15 14:06

karthik.zorfy


1 Answers

Use the aggregation framework to get the desired result. The aggregation set operator that would do the magic is $setIntersection.

The following aggregation pipeline achieves what you are after:

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 
        }
    }
])

Output:

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

UPDATE

For three or more documents to be intersected, you'd need the $reduce operator to flatten the arrays. This will allow you to intersect any number of arrays, so instead of just doing an intersection of the two arrays from docs 1 and 3, this will apply to multiple arrays as well.

Consider running the following aggregate operation:

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"] }
                }
            }
        }
    }
])
like image 173
chridam Avatar answered Sep 23 '22 12:09

chridam