0
0
MongodbHow-ToBeginner · 4 min read

How to Model One to Many Relationships in MongoDB

In MongoDB, you model one to many relationships by either embedding the many documents inside the one document or by referencing the many documents with IDs stored in the one document. Embedding is simple and fast for small related data, while referencing is better for large or growing related data sets.
📐

Syntax

There are two main ways to model one to many in MongoDB:

  • Embedding: Store an array of related documents inside the main document.
  • Referencing: Store an array of ObjectIDs referencing related documents in another collection.

Embedding example syntax:

{
_id: ObjectId(),
name: "Parent",
children: [
{ name: "Child1", age: 10 },
{ name: "Child2", age: 8 }
]
}

Referencing example syntax:

{
_id: ObjectId(),
name: "Parent",
children_ids: [ObjectId("..."), ObjectId("...")]
}
javascript
/* Embedding syntax example */
db.parents.insertOne({
  name: "Parent",
  children: [
    { name: "Child1", age: 10 },
    { name: "Child2", age: 8 }
  ]
});

/* Referencing syntax example */
db.parents.insertOne({
  name: "Parent",
  children_ids: [ObjectId("60c72b2f9b1d8e5a5f4d3a1a"), ObjectId("60c72b3a9b1d8e5a5f4d3a1b")]
});
💻

Example

This example shows embedding children documents inside a parent document and referencing children documents by their IDs.

javascript
/* Embedding example */
db.parents.insertOne({
  name: "Alice",
  children: [
    { name: "Bob", age: 12 },
    { name: "Carol", age: 9 }
  ]
});

/* Referencing example */
const child1 = db.children.insertOne({ name: "Bob", age: 12 });
const child2 = db.children.insertOne({ name: "Carol", age: 9 });

db.parents.insertOne({
  name: "Alice",
  children_ids: [child1.insertedId, child2.insertedId]
});

/* Query embedded children */
const parentEmbedded = db.parents.findOne({ name: "Alice" });

/* Query referenced children */
const parentReferenced = db.parents.findOne({ name: "Alice" });
const childrenReferenced = db.children.find({ _id: { $in: parentReferenced.children_ids } }).toArray();

parentEmbedded;
childrenReferenced;
Output
{ _id: ObjectId("..."), name: "Alice", children: [ { name: "Bob", age: 12 }, { name: "Carol", age: 9 } ] } [ { _id: ObjectId("..."), name: "Bob", age: 12 }, { _id: ObjectId("..."), name: "Carol", age: 9 } ]
⚠️

Common Pitfalls

Embedding too much data: Embedding large or growing arrays can cause document size limits and slow updates.

Referencing without indexes: Not indexing referenced IDs can cause slow queries.

Choosing the wrong model: Use embedding for small, tightly related data and referencing for large or shared data.

javascript
/* Wrong: Embedding very large array */
db.parents.insertOne({
  name: "Parent",
  children: new Array(10000).fill({ name: "Child", age: 5 })
});

/* Right: Use referencing for large child sets */
// Insert children separately and store their IDs in parent document
const childrenIds = [];
for(let i=0; i<10000; i++) {
  const child = db.children.insertOne({ name: `Child${i}`, age: 5 });
  childrenIds.push(child.insertedId);
}
db.parents.insertOne({ name: "Parent", children_ids: childrenIds });
📊

Quick Reference

  • Embedding: Use for small, fixed-size related data inside one document.
  • Referencing: Use for large, growing, or shared related data across collections.
  • Index referenced IDs: Always index referenced fields for fast lookups.
  • Document size limit: MongoDB documents max 16MB, avoid embedding large arrays.

Key Takeaways

Model one to many by embedding small related data or referencing large/growing data.
Embedding stores related documents inside one document as an array.
Referencing stores related document IDs and requires separate queries.
Avoid embedding large arrays to prevent document size limits.
Index referenced fields for efficient querying.