Cours
If you're just starting to dabble with MongoDB, you've probably come to a point where your documents are looking a little complex. These documents might have gone from flat, relational-looking pieces of data to something with nested objects, nested arrays, and maybe even four or five more levels of nesting. So, how do you query this data when it is a few layers deep?
In this short tutorial, we're going to look at dot notation within MongoDB and see how we can very quickly and easily filter our documents based on data that contains certain values in the nested fields.
When referring to dot notation, we’re talking about the separation of nested fields with a period character delimiter. For example:
root_field.nested_field_1.next_layer_nested_field_1
For every layer of nesting, we just add a period character separating that layer when querying. We’ll see more thorough examples as we progress through the tutorial.
If you’re just starting out with MongoDB, be sure to check out DataCamp’s Introduction to MongoDB in Python course.
Prerequisites
To be successful with this tutorial, you'll need to have a MongoDB instance deployed and configured. This means the expectation is that you're at a point where you're ready to start using MongoDB. You should also have at least a basic familiarity with querying collections in MongoDB. The documentation might be a good place to start if you need help.
For this example, we'll be using the following data within a "dbinc" database and a "people" collection:
[
{
"name": "Nic Raboy",
"websites": [
{
"type": "other",
"name": "Portfolio",
"url": "https://www.nraboy.com"
},
{
"type": "social",
"name": "LinkedIn",
"url": "https://www.linkedin.com/in/nraboy"
}
],
"employment": {
"employer": "MongoDB",
"address": {
"street": "1633 Broadway",
"city": "New York",
"state": "New York",
"postal_code": 10019
}
}
},
{
"name": "Tony Kim",
"websites": [
{
"type": "social",
"name": "LinkedIn",
"url": "https://www.linkedin.com/in/hyung-kim/"
},
{
"type": "coding",
"name": "GitHub",
"url": "https://github.com/hjkmines"
}
],
"employment": {
"employer": "MongoDB",
"address": {
"street": "1633 Broadway",
"city": "New York",
"state": "New York",
"postal_code": 10019
}
}
}
]
The above data represents two documents that have a fair amount of complexity because they have nested objects and arrays. As a fun fact, MongoDB supports more than 100 levels of nesting within BSON documents.
If you're planning to follow along, make sure these documents exist within your MongoDB instance.
Querying the Data Within MongoDB Using a Variety of Approaches
We're going to start simple and slowly move into more complicated territory. The good news is that complicated here doesn't necessarily mean difficult.
Let's say that we wanted to find all people within our collection who work for MongoDB. We could execute a query that looks like the following:
use dbinc;
db.people.find({
"employment.employer": "MongoDB"
});
In this example, employer exists as a nested field within the employment object. We can query against that field using dot notation, which is simply just fields separated by a period character. This would be no different than if we wanted to find all people who worked in New York. We could do something like the following:
use dbinc;
db.people.find({
"employment.address.state": "New York"
});
We queried three levels into the document in the above query, but it worked without issue.
Now, let's take a look at working with that nested array of objects. There are a few ways to query, depending on what we'd like to do.
Let's say we wanted to return all people who have a "Portfolio" website listed. We could execute a query that looks like the following:
use dbinc;
db.people.find({
"websites.name": "Portfolio"
});
The above query would return a single result because only one of the documents had a "Portfolio" listed. Notice that even though we have an array, dot notation still worked here. The fine print is that "Portfolio" must exist somewhere within that array at least once.
This is where things can get interesting.
Let's say that we want to further restrict the results that are being returned. We'd do this by adding more filter criteria, but when working with nested objects within arrays, things are a little different. Take the following, for example:
use dbinc;
db.people.find({
"websites.name": "Portfolio",
"websites.type": "social"
});
In the above example, we're saying that we want results where both "Portfolio" and "social" exist in the array, but not necessarily the same object. We only get one result back because the "Tony Kim" document has "social", but not "Portfolio". If we needed results where both fields had to exist in the same object, we wouldn't be able to use dot notation for that.
While out of the scope for this particular tutorial, using the $elemMatch operator like this would get the job done:
use dbinc;
db.people.find(
{
"websites": {
"$elemMatch": {
"name": "Portfolio",
"type": "social"
}
}
}
);
No results would be returned in the above scenario because our sample data doesn't have a matching name and type within the same object.
If you are working with arrays and you know the array index that you want to work with, you can continue to use dot notation. For example, take the following:
use dbinc;
db.people.find({
"websites.0.name": "Portfolio"
});
The above query uses the index of the array that you want to match against. In this scenario, we are wanting to return all documents where the first item in the array as a name of "Portfolio".
While out of the scope of this tutorial, it is important to call out that dot notation isn’t just restricted to read-only queries. You can use dot notation like seen here in update operations, projections, and aggregation pipelines.
Conclusion
You just got a quick introduction to using dot notation within your MongoDB queries. We learned:
- Dot notation works for nested objects.
- You can use dot notation for arrays, but with limitations depending on your expectations with those arrays.
- The
$elemMatchoperator is needed if you want to match multiple fields within a single array object. - Array indexes within dot notation can be used if you want to query for certain elements in an array.
The data in your MongoDB collections will likely not be flat, meaning at some point, you're probably going to have nested objects, nested arrays, nested arrays within objects, and any other combination of complexity. The good news is that MongoDB makes it easy to work with this information using the rich query API.
If you're not already using MongoDB, check out MongoDB Atlas or my other tutorial that demonstrates getting started with MongoDB and Docker. You can also learn about MongoDB Certification in our separate guide.
FAQs
What is dot notation in MongoDB?
Dot notation is the accessing of nested MongoDB document fields through the use of a period delimiter.
Can I filter with numerous nested fields in my queries?
Yes, your match queries can use dot notation on all, some, or none of your fields. It’s the same filter—you’re just accessing nested items.
What do I do about my unpredictable arrays?
You should make sure your arrays are not unbounded for the sake of size and performance, but querying them with dot notation will work fine and remain easy.
What if I need to update a document that has nested objects and arrays?
When using an update operation, dot notation works in both the filter part of the operation as well as the change part of the operation.
