Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongo Query On Multiple Fields Of Sub-Document

Suppose I have a collection like this:

{ "arr" : [ { "name" : "a", "num" : 1 }, { "name" : "a", "num" : 2 } ] },
{ "arr" : [ { "name" : "b", "num" : 1 }, { "name" : "a", "num" : 2 } ] },
{ "arr" : [ { "name" : "b", "num" : 1 }, { "name" : "b", "num" : 2 } ] }

and I want to find all documents who's arr contains a sub-document with a name = "b" and num = 2.

If I do a query like this:

db.collection.find({
    $and: [
        { "arr.name": "b" },
        { "arr.num": 2 }
    ]
});

it will return all documents in the collection because they each contain a sub-document with either a name of "b" or a num of 2.

I've also tried this:

db.collection.find({
    arr: [
        { "name": "b", "num": 2 }
    ]
});

which doesn't throw any errors, yet doesn't return any results.

How do you query on multiple sub-document fields in MongoDB?

like image 325
Greg Avatar asked Jan 13 '15 04:01

Greg


People also ask

How do I search for multiple fields in MongoDB?

MongoDB provides the find() that is used to find multiple values or documents from the collection. The find() method returns a cursor of the result set and prints all the documents. To find the multiple values, we can use the aggregation operations that are provided by MongoDB itself.

How do I query an array of objects in MongoDB?

Use the Array Index to Query for a Field in the Embedded Document. Using dot notation, you can specify query conditions for field in a document at a particular index or position of the array. The array uses zero-based indexing. When querying using dot notation, the field and index must be inside quotation marks.

How do I get only certain fields in MongoDB?

You can select a single field in MongoDB using the following syntax: db. yourCollectionName. find({"yourFieldName":yourValue},{"yourSingleFieldName":1,_id:0});

Where can I find nested documents in MongoDB?

Accessing embedded/nested documents – In MongoDB, you can access the fields of nested/embedded documents of the collection using dot notation and when you are using dot notation, then the field and the nested field must be inside the quotation marks.


1 Answers

This is actually what the $elemMatch operator is for even though it is often misused. It essentially performs the query conditions on each element "within" the array. All MongoDB arguments are an "and" operation unless explicitly called otherwise:

db.collection.find({ "arr": { "$elemMatch": { "name": "b", "num": 2  } } })

You probably also want to "project" here as well if you are expecting only the matched field and not that whole document:

db.collection.find(
    { "arr": { "$elemMatch": { "name": "b", "num": 2  } } },
    { "arr.$": 1 }
)

Finally to explain why your second attempt does not work, this query:

db.collection.find({
    "arr": [
        { "name": "b", "num": 2 }
    ]
})

Does not match anything because there is no actual document where "arr" contains a singular element exactly matching your conditions.

Your first example failed..:

db.collection.find({
    $and: [
        { "arr.name": "b" },
        { "arr.num": 2 }
    ]
});

Because there are several array elements that satisfy the conditions and this is not just considered that both conditions apply to the same element. That is what $elemMatch adds, and when you need more that one condition to match, then this is where you use it.

like image 165
Neil Lunn Avatar answered Sep 18 '22 15:09

Neil Lunn