8

It is basically what the title says.

Input: myArray = an array of words

I have an model that have field wordsCollection , which is an array field.

How can I find all documents of that model whose wordsCollections has at least n elements of myArray

3
  • Show db structure and what yo have tried so far to make it work. Commented Jun 9, 2016 at 12:25
  • I dont think the question is clear enough that I don't need to provide the db structure. I am not sure whether mongodb provides such an API call, so I am just thinking about iterating through all the documents.... Of course, it sounds really bad Commented Jun 9, 2016 at 12:51
  • Are the items of myArray and wordsCollection unique? Commented Jun 9, 2016 at 13:33

1 Answer 1

10

Let say we have the following documents in our collection:

{ "_id" : ObjectId("5759658e654456bf4a014d01"), "a" : [ 1, 3, 9, 2, 9, 0 ] }
{ "_id" : ObjectId("5759658e654456bf4a014d02"), "a" : [ 0, 8, 1 ] }
{ "_id" : ObjectId("5759658e654456bf4a014d03"), "a" : [ 0, 8, 432, 9, 34, -3 ] }
{ "_id" : ObjectId("5759658e654456bf4a014d04"), "a" : [ 0, 0, 4, 3, 2, 7 ] }

and the following input array and n = 2

var inputArray = [1, 3, 0];

We can return those documents where the array field contains at least n elements of a given array using the aggregation framework.

The $match selects only those documents with the array's length greater or equals to n. This reduce the amount of data to be processed in down in the pipeline.

The $redact pipeline operator use a logical condition processing using the $cond operator and the special operations $$KEEP to "keep" the document where the logical condition is true or $$PRUNE to "discard" the document where the condition is false.

In our case, the condition is $gte which returns true if the $size of the intersection of the two arrays, which we compute using the $setIntersection operator is greater than or equal 2.

db.collection.aggregate(
    [ 
        { "$match": { "a.1": { "$exists": true } } }, 
        { "$redact": { 
            "$cond": [ 
                { "$gte": [ 
                    { "$size": { "$setIntersection": [ "$a", inputArray ] } }, 
                    2
                ]},
                "$$KEEP", 
                "$$PRUNE" 
            ]
        }}
    ]
)

which produces:

{ "_id" : ObjectId("5759658e654456bf4a014d01"), "a" : [ 1, 3, 9, 2, 9, 0 ] }
{ "_id" : ObjectId("5759658e654456bf4a014d02"), "a" : [ 0, 8, 1 ] }
{ "_id" : ObjectId("5759658e654456bf4a014d04"), "a" : [ 0, 0, 4, 3, 2, 7 ] }
Sign up to request clarification or add additional context in comments.

1 Comment

Your solution is amazing. I learn a lot of mongodb from it. Thks :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.