Link MongoDB Documents

MongoDBMongoDBBeginner
Practice Now

Introduction

In this lab, you will learn how to establish relationships between MongoDB documents, including creating document references, updating related data, querying linked documents, removing document links, and ensuring data integrity. The lab covers fundamental techniques for working with MongoDB relationships, such as using the $lookup aggregation stage to join collections and updating documents across related collections. By the end of the lab, you will have a solid understanding of how to manage relationships in your MongoDB database.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL mongodb(("`MongoDB`")) -.-> mongodb/BasicOperationsGroup(["`Basic Operations`"]) mongodb(("`MongoDB`")) -.-> mongodb/QueryOperationsGroup(["`Query Operations`"]) mongodb(("`MongoDB`")) -.-> mongodb/ArrayandEmbeddedDocumentsGroup(["`Array and Embedded Documents`"]) mongodb(("`MongoDB`")) -.-> mongodb/IndexingGroup(["`Indexing`"]) mongodb(("`MongoDB`")) -.-> mongodb/RelationshipsGroup(["`Relationships`"]) mongodb/BasicOperationsGroup -.-> mongodb/update_document("`Update Document`") mongodb/BasicOperationsGroup -.-> mongodb/delete_document("`Delete Document`") mongodb/QueryOperationsGroup -.-> mongodb/find_documents("`Find Documents`") mongodb/QueryOperationsGroup -.-> mongodb/project_fields("`Project Fields`") mongodb/ArrayandEmbeddedDocumentsGroup -.-> mongodb/create_embedded_documents("`Create Embedded Documents`") mongodb/IndexingGroup -.-> mongodb/create_index("`Create Index`") mongodb/RelationshipsGroup -.-> mongodb/create_document_references("`Create Document References`") mongodb/RelationshipsGroup -.-> mongodb/link_related_documents("`Link Related Documents`") subgraph Lab Skills mongodb/update_document -.-> lab-422087{{"`Link MongoDB Documents`"}} mongodb/delete_document -.-> lab-422087{{"`Link MongoDB Documents`"}} mongodb/find_documents -.-> lab-422087{{"`Link MongoDB Documents`"}} mongodb/project_fields -.-> lab-422087{{"`Link MongoDB Documents`"}} mongodb/create_embedded_documents -.-> lab-422087{{"`Link MongoDB Documents`"}} mongodb/create_index -.-> lab-422087{{"`Link MongoDB Documents`"}} mongodb/create_document_references -.-> lab-422087{{"`Link MongoDB Documents`"}} mongodb/link_related_documents -.-> lab-422087{{"`Link MongoDB Documents`"}} end

Create Document References

In this step, you'll learn how to create document references in MongoDB, which is a fundamental technique for establishing relationships between different collections.

First, let's start the MongoDB shell:

mongosh

We'll create two collections to demonstrate document referencing: authors and books. This is a common scenario where books are linked to their authors.

Create the authors collection:

use library_database

db.authors.insertMany([
    {
        _id: ObjectId("660a1f5c9b8f8b1234567890"),
        name: "Jane Austen",
        nationality: "British"
    },
    {
        _id: ObjectId("660a1f5c9b8f8b1234567891"),
        name: "George Orwell",
        nationality: "British"
    }
])

Example output:

{
  acknowledged: true,
  insertedIds: {
    '0': ObjectId("660a1f5c9b8f8b1234567890"),
    '1': ObjectId("660a1f5c9b8f8b1234567891")
  }
}

Now, let's create the books collection with references to authors:

db.books.insertMany([
    {
        title: "Pride and Prejudice",
        author_id: ObjectId("660a1f5c9b8f8b1234567890"),
        year: 1813
    },
    {
        title: "1984",
        author_id: ObjectId("660a1f5c9b8f8b1234567891"),
        year: 1949
    }
])

Example output:

{
  acknowledged: true,
  insertedIds: {
    '0': ObjectId("660b2a1c9b8f8b1234567892"),
    '1': ObjectId("660b2a1c9b8f8b1234567893")
  }
}

Let's verify the references by querying books with their author details:

db.books.aggregate([
    {
        $lookup: {
            from: "authors",
            localField: "author_id",
            foreignField: "_id",
            as: "author_details"
        }
    }
])

This demonstrates how to create document references in MongoDB. We've linked books to their authors using the author_id field, which contains the ObjectId of the corresponding author.

In this step, you'll learn how to update related documents in MongoDB, building upon the document references we created in the previous step.

First, ensure you're connected to the MongoDB shell and using the library database:

mongosh
use library_database

Let's update an author's information. We'll modify Jane Austen's details:

db.authors.updateOne(
    { _id: ObjectId("660a1f5c9b8f8b1234567890") },
    {
        $set: {
            birth_year: 1775,
            notable_works: ["Pride and Prejudice", "Sense and Sensibility"]
        }
    }
)

Example output:

{
  acknowledged: true,
  insertedId: null,
  matchedCount: 1,
  modifiedCount: 1
}

Now, let's update a book's details while maintaining its reference:

db.books.updateOne(
    { title: "Pride and Prejudice" },
    {
        $set: {
            genre: "Romance",
            pages: 432,
            rating: 4.5
        }
    }
)

Example output:

{
  acknowledged: true,
  insertedId: null,
  matchedCount: 1,
  modifiedCount: 1
}

Let's verify the updates by querying the full details:

db.authors.findOne({ name: "Jane Austen" })
db.books.findOne({ title: "Pride and Prejudice" })

This demonstrates how to update related documents while maintaining their references. The $set operator allows you to add or modify specific fields without replacing the entire document.

Query Linked Documents

In this step, you'll learn advanced techniques for querying linked documents in MongoDB using the $lookup aggregation pipeline stage.

First, ensure you're connected to the MongoDB shell:

mongosh
use library_database

Let's perform a simple lookup to join books with their authors:

db.books.aggregate([
    {
        $lookup: {
            from: "authors",
            localField: "author_id",
            foreignField: "_id",
            as: "author_details"
        }
    }
])

Now, let's create a more complex query to filter books by author nationality:

db.books.aggregate([
    {
        $lookup: {
            from: "authors",
            localField: "author_id",
            foreignField: "_id",
            as: "author_details"
        }
    },
    {
        $match: {
            "author_details.nationality": "British"
        }
    },
    {
        $project: {
            title: 1,
            year: 1,
            "author_name": { $arrayElemAt: ["$author_details.name", 0] }
        }
    }
])

Let's create another query to find books published after 1900:

db.books.aggregate([
    {
        $lookup: {
            from: "authors",
            localField: "author_id",
            foreignField: "_id",
            as: "author_details"
        }
    },
    {
        $match: {
            year: { $gt: 1900 }
        }
    },
    {
        $project: {
            title: 1,
            year: 1,
            "author_name": { $arrayElemAt: ["$author_details.name", 0] }
        }
    }
])

These queries demonstrate different ways to query and combine linked documents using MongoDB's aggregation framework.

In this step, you'll learn how to remove document links and manage related documents in MongoDB.

First, ensure you're connected to the MongoDB shell:

mongosh
use library_database

Let's start by removing a specific book while keeping the author:

db.books.deleteOne({ title: "1984" })

Example output:

{ acknowledged: true, deletedCount: 1 }

Now, let's remove an author and all their associated books using a multi-step process:

// First, find the author's ID
const authorToRemove = db.authors.findOne({ name: "George Orwell" })

// Delete all books by this author
db.books.deleteMany({ author_id: authorToRemove._id })

// Then remove the author
db.authors.deleteOne({ _id: authorToRemove._id })

Let's demonstrate a soft delete approach by adding a status field:

db.books.updateOne(
    { title: "Pride and Prejudice" },
    {
        $set: {
            status: "archived",
            archived_date: new Date()
        }
    }
)

To query only active books:

db.books.find({
    $or: [
        { status: { $exists: false } },
        { status: { $ne: "archived" } }
    ]
})

These methods show different strategies for managing document links and removing related documents.

Check Data Integrity

In this step, you'll learn techniques to ensure data integrity in MongoDB document relationships.

First, ensure you're connected to the MongoDB shell:

mongosh
use library_database

Create a validation rule for the authors collection:

db.createCollection("authors", {
   validator: {
      $jsonSchema: {
         bsonType: "object",
         required: ["name", "nationality"],
         properties: {
            name: {
               bsonType: "string",
               description: "must be a string and is required"
            },
            nationality: {
               bsonType: "string",
               description: "must be a string and is required"
            },
            birth_year: {
               bsonType: "int",
               minimum: 1500,
               maximum: 2023,
               description: "must be an integer between 1500 and 2023"
            }
         }
      }
   }
})

Let's create a function to check orphaned references:

function checkOrphanedReferences() {
    const orphanedBooks = db.books.aggregate([
        {
            $lookup: {
                from: "authors",
                localField: "author_id",
                foreignField: "_id",
                as: "author_exists"
            }
        },
        {
            $match: {
                author_exists: { $size: 0 }
            }
        }
    ]).toArray()

    print("Orphaned Books:", orphanedBooks.length)
    return orphanedBooks
}

checkOrphanedReferences()

Create a data integrity check for book documents:

function validateBookDocuments() {
    const invalidBooks = db.books.find({
        $or: [
            { title: { $not: { $type: "string" } } },
            { year: { $not: { $type: "int" } } },
            { year: { $lt: 0 } }
        ]
    }).toArray()

    print("Invalid Books:", invalidBooks.length)
    return invalidBooks
}

validateBookDocuments()

Demonstrate a referential integrity check:

function checkReferentialIntegrity() {
    const authorIds = db.authors.distinct("_id")
    const bookAuthorIds = db.books.distinct("author_id")

    const missingAuthors = bookAuthorIds.filter(
        id => !authorIds.some(authorId => authorId.equals(id))
    )

    print("Missing Author References:", missingAuthors.length)
    return missingAuthors
}

checkReferentialIntegrity()

Summary

In this lab, you learned how to create document references in MongoDB, which is a fundamental technique for establishing relationships between different collections. You created two collections, "authors" and "books", and linked books to their authors using the "author_id" field. You also learned how to query the linked documents using the $lookup aggregation stage. Additionally, you explored how to update related documents, query linked documents, remove document links, and ensure data integrity when working with document references in MongoDB.

Other MongoDB Tutorials you may like