Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find documents whose array field contains at least n elements of a given array

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

like image 295
Mr Cold Avatar asked Jun 09 '16 12:06

Mr Cold


People also ask

How do I query an array field in MongoDB?

To query if the array field contains at least one element with the specified value, use the filter { <field>: <value> } where <value> is the element value. To specify conditions on the elements in the array field, use query operators in the query filter document: { <array field>: { <operator1>: <value1>, ... } }

How do I filter an array element in MongoDB?

Filter MongoDB Array Element Using $Filter Operator This operator uses three variables: input – This represents the array that we want to extract. cond – This represents the set of conditions that must be met. as – This optional field contains a name for the variable that represent each element of the input array.

What is $size in MongoDB?

The $size operator in MongoDB is used to fetch the document that has an array field of a specific size. The $size only deals with arrays and accepts only numeric values as a parameter.

How do I find the length of an array in MongoDB?

The $size operator matches any array with the number of elements specified by the argument. For example: db. collection.


1 Answers

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 ] }
like image 193
styvane Avatar answered Sep 21 '22 20:09

styvane