Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose get docs matching the array

I have a schema like this

{
    members: [{
         type: Schema.Types.ObjectId,
         ref: 'User'
    }]
    createdAt: {
        type: Date,
        default: Date.now
    }
    ...
}

And the docs are

1-

{
    members:
    ["some id 1", "some id 2"]
},
createdAt: "someTime ago"

2-

{
    members:
    ["some id 1", "some id 2", "some id 3"]
},
createdAt: "someTime ago"

I want to find the docs which match the exact an array of elements

['some id 1', 'some id 2']

ie doc 1 in the above sample docs

How this could be possible?
Any help would be appreciated.

like image 323
muhammed basil Avatar asked Apr 04 '14 07:04

muhammed basil


People also ask

How do I find a particular element in an array 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>, ... } }

Does find return an array Mongoose?

Return valueThe returned value could be an array of documents, a single document if it matches only one, or an empty array if no document is matched.

How do I query an array of objects in MongoDB?

To search the array of object in MongoDB, you can use $elemMatch operator. This operator allows us to search for more than one component from an array object.


1 Answers

As long as you do realize that you are matching on the ObjectId and not actually anything in the referenced collection you can use the $in operator:

db.collection.find({ "members": { "$in": [ "some id 1", "some id 2" ] } })

Where of course those are your actual ObjectId values.

But if you really mean a document that has exactly that array, then you just pass in the array:

db.collection.find({ "members": [ "some id 1", "some id 2" ] })

And if it must have both the elements but could have others then currently you need to use an $and expression:

db.collection.find({ "$and": [ 
    { "members": "some id 1" },
    { "members": "some id 2" } 
]})

But from release 2.6 an on-wards you can properly use the $all operator to effectively do the same:

db.collection.find({ "members": { "$all": [ "some id 1", "some id 2" ] } })

The other form is matching those two elements only, but in any order. So there are two approaches:

db.collection.find({ "$or": [
    { "members": [ "some id 1", "some id 2" ] },
    { "members": [ "some id 2", "some id 1" ] }
]})

This uses a logical $or to say that the array must be exact but can be arranged either way. And the other approach:

db.collection.find({ "$and": [ 
    { "members": "some id 1" },
    { "members": "some id 2" }
    { "members": { "$size": 2 } }
]})

So this would use $size in order to make sure that when the array contained both of the elements that matched that is also only had just two elements. Which is a nicer syntax than using $or, especially for larger arrays.

And in the future releases as mentioned this gets even cleaner:

db.collection.find({ "$and": [ 
    { "members": { "$all": [ "some id 1", "some id 2" ] } },
    { "members": { "$size": 2 } }
]})

That fairly much covers every interpretation

like image 153
Neil Lunn Avatar answered Sep 28 '22 09:09

Neil Lunn