Document relationships

Document relationships

One-to-one, one-to-many and many-to-many describe how records relate. They do not by themselves decide whether to embed or reference; consider reads, updates and growth too.

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.

Before working through the examples, make sure you can connect with mongosh and select your database. Use a practice database for writes and deletions.

  1. By the end of this lesson

    Model a relationship and explain why its data is embedded or referenced.

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"
      }
    });
    {
      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
    });
    {
      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!" }
      ]
    });
    {
      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!" }
    ]);
    {
      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 }
    ]);
    {
      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.

What to remember

One-to-one, one-to-many and many-to-many describe how records relate. They do not by themselves decide whether to embed or reference; consider reads, updates and growth too.

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.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: JSON Schema validation →