One-to-One, One-to-Many, Many-to-Many Relationships in MongoDB
In traditional relational databases, relationships between tables are created using foreign keys. MongoDB, being a NoSQL database, doesn't use foreign keys or joins in the same way, but it still allows you to model relationships using embedded documents or references.
One-to-One Relationship
In a one-to-one relationship, one document is associated with exactly one other document. For example, a user might have one profile.
Example: A user has one profile document containing extra details like bio and location.
Option 1: Embedding
db.users.insertOne({
name: "Alice",
email: "alice@example.com",
profile: {
bio: "Web Developer",
location: "New York"
}
});
Output:
{ acknowledged: true, insertedId: ObjectId("...") }
This approach is ideal when profile data is only used with the user and isn’t large or frequently updated independently.
Option 2: Referencing
// Insert into profiles
const profileId = db.profiles.insertOne({
bio: "Web Developer",
location: "New York"
}).insertedId;
// Insert into users
db.users.insertOne({
name: "Alice",
email: "alice@example.com",
profileId: profileId
});
Output:
{ acknowledged: true, insertedId: ObjectId("...") }
Use referencing when the profile might be reused, updated often, or stored separately due to size.
Q: Should I embed or reference profile info?
A: Embed it if it's tightly coupled and small. Reference it if it's large, reused, or separately managed.
One-to-Many Relationship
In a one-to-many relationship, one document is associated with many others. For example, a blog post can have many comments.
Option 1: Embedding (Good for small, infrequent updates)
db.posts.insertOne({
title: "MongoDB Relationships",
content: "Understanding how to model data...",
comments: [
{ user: "John", text: "Great post!" },
{ user: "Sarah", text: "Very helpful, thanks!" }
]
});
Output:
{ acknowledged: true, insertedId: ObjectId("...") }
Embedding comments works well when they are small and usually retrieved together with the post.
Option 2: Referencing (Better for high-volume or independent access)
const postId = db.posts.insertOne({
title: "MongoDB Relationships",
content: "Understanding how to model data..."
}).insertedId;
db.comments.insertMany([
{ postId: postId, user: "John", text: "Great post!" },
{ postId: postId, user: "Sarah", text: "Very helpful, thanks!" }
]);
Output:
{ acknowledged: true, insertedIds: { "0": ObjectId("..."), "1": ObjectId("...") } }
Use referencing when there are many comments or they need to be queried or paginated separately.
Q: Why not always embed?
A: Embedding leads to document growth. MongoDB documents have a 16MB size limit, and large embedded arrays can hurt performance.
Many-to-Many Relationship
In a many-to-many relationship, multiple documents relate to multiple others. Example: Students can enroll in multiple courses, and each course can have many students.
Model with Cross-References
const student1 = db.students.insertOne({ name: "Amit" }).insertedId;
const student2 = db.students.insertOne({ name: "Priya" }).insertedId;
const course1 = db.courses.insertOne({ title: "Maths" }).insertedId;
const course2 = db.courses.insertOne({ title: "Physics" }).insertedId;
db.enrollments.insertMany([
{ studentId: student1, courseId: course1 },
{ studentId: student1, courseId: course2 },
{ studentId: student2, courseId: course2 }
]);
Output:
{ acknowledged: true, insertedIds: { "0": ObjectId("..."), "1": ObjectId("..."), "2": ObjectId("...") } }
This pattern is called a junction collection, where we create an explicit mapping between two collections.
Q: Can we embed courses inside students?
A: Not if the relationship is many-to-many. Embedding would lead to data duplication and inconsistency.
Summary
- One-to-One: Embed if small, reference if reused or large.
- One-to-Many: Embed if small and tightly bound, reference if large or accessed separately.
- Many-to-Many: Always use referencing with a linking/junction collection.
Understanding these relationship patterns helps you design efficient, scalable, and maintainable MongoDB schemas.