Embedded documents allow us to store one document inside another document. They are useful when related information belongs together, such as a student's address, an employee's contact details, or a product's specifications.
An embedded document is a document stored as the value
of a field inside another document. It uses curly braces
{} to represent its fields.
{
name: "Rahul",
age: 20,
address: {
city: "Patna",
state: "Bihar",
pincode: 800001
}
}
Here, address is an embedded document
containing the fields city,
state, and pincode.
The main document stores the student's name and age, while the embedded document stores the address details.
Embedded documents are useful when related information should be stored together.
{
name: "Amit",
department: "IT",
contact: {
email: "amit@example.com",
phone: "9876543210"
}
}
The employee's contact information is grouped inside
the contact field.
We can insert embedded documents using
insertOne() or insertMany().
db.embedded_students.insertOne({
name: "Rahul",
age: 20,
course: "Java",
address: {
city: "Patna",
state: "Bihar",
pincode: 800001
}
})
db.embedded_students.insertMany([
{
name: "Priya",
course: "Python",
address: {
city: "Gaya",
state: "Bihar"
}
},
{
name: "Aman",
course: "JavaScript",
address: {
city: "Aurangabad",
state: "Bihar"
}
}
])
Each student document can contain its own embedded address document.
MongoDB uses dot notation to access fields inside an embedded document. Put the complete field path inside quotation marks in a query.
db.embedded_students.find({
"address.city": "Patna"
})
This finds documents whose embedded address has
the city value "Patna".
db.embedded_students.find({
"address.state": "Bihar"
})
db.embedded_students.find({
"address.pincode": 800001
})
Dot notation lets us query a nested field without matching the entire embedded document.
MongoDB can match an entire embedded document when the complete embedded value matches, including its field values and field order.
{
name: "Rahul",
address: {
city: "Patna",
state: "Bihar"
}
}
db.embedded_students.find({
address: {
city: "Patna",
state: "Bihar"
}
})
This matches the specified embedded document as a whole. If the address contains additional fields, or the fields appear in a different order, this exact embedded-document match may not succeed.
When you only need to check particular nested fields, dot notation is generally more flexible.
We can update a nested field using dot notation
with the $set operator.
db.embedded_students.updateOne(
{ name: "Rahul" },
{
$set: {
"address.city": "Delhi"
}
}
)
This changes the city field without replacing the entire address document.
db.embedded_students.updateOne(
{ name: "Rahul" },
{
$set: {
"address.landmark": "Main Market"
}
}
)
If the address document exists, this adds the
landmark field to it.
db.embedded_students.findOne({
name: "Rahul"
})
Projection allows us to display selected nested fields from an embedded document.
db.embedded_students.find(
{},
{
_id: 0,
name: 1,
"address.city": 1
}
)
This displays each student's name and city while
excluding the _id field.
db.embedded_students.find(
{},
{
_id: 0,
address: 1
}
)
This returns the complete embedded address document without the other top-level fields.
MongoDB can store arrays of embedded documents. This is useful when one record contains multiple related items, such as marks for different subjects.
{
name: "Priya",
results: [
{
subject: "Java",
marks: 85
},
{
subject: "Python",
marks: 92
}
]
}
The results field is an array, and
each element is an embedded document.
db.embedded_students.find({
results: {
$elemMatch: {
subject: "Python",
marks: { $gte: 90 }
}
}
})
The $elemMatch operator ensures that
both conditions match the same element in the
results array.
| Embedded Documents | Separate Collections |
|---|---|
| Related data is stored inside a parent document. | Related data is stored in separate documents or collections. |
| Often convenient for data read together. | Useful when data is independently managed or shared. |
| Can reduce the need for additional queries. | May require additional queries or aggregation with $lookup. |
| Suitable for bounded, closely related information. | Suitable for large or independently growing related data. |
Choose the design based on how the application reads, updates, and manages the data. Embedding is not always the best choice, especially for very large or unbounded arrays.
{} for embedded documents."address.city", to query nested fields.$set with dot notation to update a nested field.$elemMatch can require multiple conditions to match the same array element.
Create a collection named
practice_embedded and insert these documents:
db.practice_embedded.insertMany([
{
_id: 1,
name: "Rahul",
age: 22,
address: {
city: "Patna",
state: "Bihar"
},
course: "Java"
},
{
_id: 2,
name: "Priya",
age: 19,
address: {
city: "Gaya",
state: "Bihar"
},
course: "Python"
},
{
_id: 3,
name: "Aman",
age: 21,
address: {
city: "Delhi",
state: "Delhi"
},
course: "JavaScript"
}
])
Run the insertion command only once, or clear the test collection before inserting the same sample data again.
1. What is an embedded document?
2. Which notation queries the city field inside address?
3. Which operator updates a nested field?