How to query nested objects?

MongodbSyntaxNestedMongodb QueryBson

Mongodb Problem Overview


I have a problem when querying mongoDB with nested objects notation:

db.messages.find( { headers : { From: "[email protected]" } } ).count()
0
db.messages.find( { 'headers.From': "[email protected]" }  ).count()
5

I can't see what I am doing wrong. I am expecting nested object notation to return the same result as the dot notation query. Where am I wrong?

Mongodb Solutions


Solution 1 - Mongodb

db.messages.find( { headers : { From: "[email protected]" } } )

This queries for documents where headers equals { From: ... }, i.e. contains no other fields.


db.messages.find( { 'headers.From': "[email protected]" } )

This only looks at the headers.From field, not affected by other fields contained in, or missing from, headers.


Dot-notation docs

Solution 2 - Mongodb

The two query mechanism work in different ways, as suggested in the docs at the section Subdocuments:

When the field holds an embedded document (i.e, subdocument), you can either specify the entire subdocument as the value of a field, or “reach into” the subdocument using dot notation, to specify values for individual fields in the subdocument:

Equality matches within subdocuments select documents if the subdocument matches exactly the specified subdocument, including the field order.


In the following example, the query matches all documents where the value of the field producer is a subdocument that contains only the field company with the value 'ABC123' and the field address with the value '123 Street', in the exact order:

db.inventory.find( {
    producer: {
        company: 'ABC123',
        address: '123 Street'
    }
});

Solution 3 - Mongodb

Since there is a lot of confusion about queries MongoDB collection with sub-documents, I thought its worth to explain the above answers with examples:

First I have inserted only two objects in the collection namely: message as:

> db.messages.find().pretty()
{
	"_id" : ObjectId("5cce8e417d2e7b3fe9c93c32"),
	"headers" : {
		"From" : "[email protected]"
	}
}
{
	"_id" : ObjectId("5cce8eb97d2e7b3fe9c93c33"),
	"headers" : {
		"From" : "[email protected]",
		"To" : "[email protected]"
	}
}
>

> So what is the result of query: db.messages.find({headers: {From: "[email protected]"} }).count()

It should be one because these queries for documents where headers equal to the object {From: "[email protected]"}, only i.e. contains no other fields or we should specify the entire sub-document as the value of a field.

So as per the answer from @Edmondo1984 >> Equality matches within sub-documents select documents if the subdocument matches exactly the specified sub-document, including the field order.

From the above statements, what is the below query result should be?

> db.messages.find({headers: {To: "[email protected]", From: "[email protected]"}  }).count()
0

And what if we will change the order of From and To i.e same as sub-documents of second documents?

> db.messages.find({headers: {From: "[email protected]", To: "[email protected]"}  }).count()
1

> so, it matches exactly the specified sub-document, including the field order.

For using dot operator, I think it is very clear for every one. Let's see the result of below query:

> db.messages.find( { 'headers.From': "[email protected]" }  ).count()
2

I hope these explanations with the above example will make someone more clarity on find query with sub-documents.

Solution 4 - Mongodb

I can't believe no one wrote this! Just use $elemMatch and it should work:

db.messages.find( { headers : { $elemMatch: { From: "[email protected]" } } } ).count()

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEdmondo1984View Question on Stackoverflow
Solution 1 - Mongodbshx2View Answer on Stackoverflow
Solution 2 - MongodbEdmondo1984View Answer on Stackoverflow
Solution 3 - Mongodbkrishna PrasadView Answer on Stackoverflow
Solution 4 - MongodbIglesias LeonardoView Answer on Stackoverflow