How to Model Many-to-Many Relationships in MongoDB
In MongoDB, model a
many-to-many relationship by using referencing with arrays of ObjectIds in both collections or by creating a separate linking collection. This approach keeps data flexible and avoids duplication while allowing efficient queries.Syntax
To model many-to-many relationships, you typically use references between documents. Each document stores an array of ObjectId values pointing to related documents in another collection.
Alternatively, you can create a linking collection that stores pairs of references to connect documents from both sides.
- Referencing: Store arrays of
ObjectIdin both collections. - Linking Collection: Create a separate collection with documents containing references to both related documents.
json
/* Referencing example */ { _id: ObjectId("..."), name: "Author A", book_ids: [ObjectId("..."), ObjectId("...")] } { _id: ObjectId("..."), title: "Book 1", author_ids: [ObjectId("..."), ObjectId("...")] } /* Linking collection example */ { _id: ObjectId("..."), author_id: ObjectId("..."), book_id: ObjectId("...") }
Example
This example shows two collections, authors and books, referencing each other to model a many-to-many relationship.
javascript
use library // Insert authors const author1 = db.authors.insertOne({ name: "Author A", book_ids: [] }); const author2 = db.authors.insertOne({ name: "Author B", book_ids: [] }); // Insert books const book1 = db.books.insertOne({ title: "Book 1", author_ids: [] }); const book2 = db.books.insertOne({ title: "Book 2", author_ids: [] }); // Update authors with book references db.authors.updateOne({ _id: author1.insertedId }, { $set: { book_ids: [book1.insertedId, book2.insertedId] } }); db.authors.updateOne({ _id: author2.insertedId }, { $set: { book_ids: [book2.insertedId] } }); // Update books with author references db.books.updateOne({ _id: book1.insertedId }, { $set: { author_ids: [author1.insertedId] } }); db.books.updateOne({ _id: book2.insertedId }, { $set: { author_ids: [author1.insertedId, author2.insertedId] } }); // Query: Find books by Author A const authorA = db.authors.findOne({ name: "Author A" }); const booksByAuthorA = db.books.find({ _id: { $in: authorA.book_ids } }).toArray(); booksByAuthorA;
Output
[
{ _id: ObjectId("..."), title: "Book 1", author_ids: [ObjectId("...")] },
{ _id: ObjectId("..."), title: "Book 2", author_ids: [ObjectId("..."), ObjectId("...")] }
]
Common Pitfalls
- Embedding too much data: Embedding entire related documents can cause duplication and update issues.
- Not using references: Without references, querying many-to-many relations becomes inefficient.
- Ignoring linking collections: For complex relations, a linking collection keeps data normalized and queries simpler.
json
/* Wrong: Embedding full related documents causes duplication */ { _id: ObjectId("..."), name: "Author A", books: [ { _id: ObjectId("..."), title: "Book 1" }, { _id: ObjectId("..."), title: "Book 2" } ] } /* Right: Use references instead */ { _id: ObjectId("..."), name: "Author A", book_ids: [ObjectId("..."), ObjectId("...")] }
Quick Reference
- Use arrays of
ObjectIdto reference related documents. - Consider a linking collection for complex many-to-many relations.
- Avoid embedding full related documents to prevent duplication.
- Keep references consistent on both sides for easier queries.
Key Takeaways
Model many-to-many in MongoDB using arrays of ObjectId references or a linking collection.
Avoid embedding full related documents to prevent data duplication and update issues.
Keep references consistent in both collections for efficient querying.
Use a linking collection when relationships are complex or require additional attributes.
Always design your schema based on your query patterns and data update needs.