NoSQL Databases: Architecture, Data Models, and Practical Use

Understand why NoSQL databases emerged and how their architectures differ from relational systems. This tutorial explores document, key-value, wide-column, and graph databases; data modeling; partitioning; sharding; replication; consistency; CAP; transactions; caching; CQRS; microservices; and polyglot persistence. It concludes with practical architecture decisions for ownership, data flow, scaling, performance, and failure scenarios.

1. Lesson 1: Why NoSQL Exists Demo 2. Lesson 2: Relational vs. NoSQL: The Fundamental Differences Demo 3. Lesson 3: The Distributed Systems Foundations of NoSQL Demo 4. Lesson 4: Document Databases Demo 5. Lesson 5: Key-Value Databases Demo 6. Lesson 6: Wide-Column Databases Locked 7. Lesson 7: Graph Databases Locked 8. Lesson 8: Data Modeling in NoSQL Locked 9. Lesson 9: Partitioning and Sharding Locked 10. Lesson 10: Replication Locked 11. Lesson 11: Consistency Models Locked 12. Lesson 12: CAP Theorem in Practice Locked 13. Lesson 13: Transactions in NoSQL Locked 14. Lesson 14: ACID, BASE, and Eventual Consistency Locked 15. Lesson 15: Handling Relationships Without Relational Joins Locked 16. Lesson 16: MongoDB Architecture and Design Locked 17. Lesson 17: Redis Architecture and Use Cases Locked 18. Lesson 18: Cassandra Architecture and Data Modeling Locked 19. Lesson 19: DynamoDB Architecture and Design Locked 20. Lesson 20: Graph Databases with Neo4j Locked 21. Lesson 21: NoSQL in Microservices Locked 22. Lesson 22: NoSQL, Caching, CQRS, and Event-Driven Architecture Locked 23. Lesson 23: Choosing the Right Database: Architecture Decision Framework Locked 24. Lesson 24: Designing a Polyglot Persistence System Locked 25. Lesson 25: Assigning Data Ownership to Services Locked 26. Lesson 26: Designing the Database Architecture Locked 27. Lesson 27: Designing the Data Flow Locked 28. Lesson 28: Consistency, Replication, and Failure Scenarios Locked 29. Lesson 29: Scaling and Performance Architecture Locked 30. Lesson 30: Defending the Architecture: ADR and Architectural Trade-offs Locked

Lesson 4: Document Databases

Demo

We can now begin examining the major NoSQL data models, starting with document databases. This lesson introduces the document model and explains how JSON-like documents, collections, embedded data, references, and flexible schemas change the way applications store and retrieve information. MongoDB will be used as the primary example so that the concepts can be connected to a real technology.

What Is a Document Database?

A document database is a NoSQL database that stores information as documents rather than rows in relational tables. A document usually represents a complete business object or aggregate, and its structure can contain nested objects and arrays. MongoDB is one of the most widely used examples of a document database.

Consider an online learning platform. A course might contain its title, description, instructor information, categories, and lessons. In a relational database, this information might be distributed across several tables. In MongoDB, much of it can potentially be represented as one document.

{
  "courseId": 101,
  "title": "ASP.NET Core Fundamentals",
  "instructor": {
    "name": "John Smith",
    "email": "john@example.com"
  },
  "lessons": [
    {
      "title": "Dependency Injection",
      "duration": 30
    },
    {
      "title": "Middleware",
      "duration": 25
    }
  ]
}

The important architectural idea is that a document can closely resemble the object that the application works with. This can reduce the impedance mismatch between application objects and database structures.

JSON and BSON

Document databases commonly use a JSON-like representation. MongoDB internally uses BSON, which means Binary JSON. BSON supports JSON-like structures while also providing additional data types such as dates, binary data, and specific numeric types.

A C# application might work with a class such as:

public class Course
{
    public string Id { get; set; }
    public string Title { get; set; }
    public Instructor Instructor { get; set; }
    public List<Lesson> Lessons { get; set; }
}

The MongoDB .NET Driver can map this object to a MongoDB document. This makes MongoDB particularly natural for applications built around object-oriented domain models.

Collections

MongoDB organizes documents into collections. A collection is roughly comparable to a table in a relational database, although the concepts are not identical.

For example, an online learning platform could contain collections such as:

Courses
Students
Enrollments
Reviews

Documents inside the same collection do not necessarily need to have exactly the same structure. This is different from a traditional SQL table, where the database normally expects rows to conform to a defined schema.

Embedded Documents

One of the most important features of document databases is the ability to embed related data inside a document.

For example, instead of having separate Courses and Lessons tables, a course can contain its lessons directly:

{
  "courseId": 101,
  "title": "C# Fundamentals",
  "lessons": [
    { "title": "Classes", "duration": 20 },
    { "title": "Interfaces", "duration": 25 }
  ]
}

This is useful when the embedded information belongs strongly to the parent object and is normally retrieved together with it. If the application almost always loads a course together with its lessons, embedding can provide a very efficient access pattern.

However, embedding is not always appropriate. If millions of students independently reference the same instructor, embedding the instructor inside every course could create excessive duplication and make updates difficult.

References

Instead of embedding data, a document can store a reference to another document.

For example:

{
  "courseId": 101,
  "title": "C# Fundamentals",
  "instructorId": "I100"
}

The instructor can then exist separately in an Instructors collection.

References are useful when the related entity is large, frequently updated, shared by many documents, or has an independent lifecycle. The trade-off is that retrieving the complete information may require additional database operations.

Therefore, document modeling commonly involves deciding between embedding and referencing.

Flexible Schemas

Document databases are often described as schema-flexible. This means that documents in a collection can evolve without requiring the same kind of table migration normally associated with relational databases.

For example, an older product document might contain:

{
  "name": "Laptop",
  "price": 1200
}

A newer version might contain:

{
  "name": "Laptop",
  "price": 1200,
  "brand": "Dell",
  "screenSize": 15.6
}

This flexibility is valuable when different types of entities have different attributes or when requirements change frequently. However, flexibility can become a problem if it is not controlled. Poorly managed documents can eventually contain several incompatible versions of the same concept.

For production systems, schema validation, application validation, versioning, and migration strategies may still be necessary. Schema flexibility does not mean schema discipline is unnecessary.

Querying Documents

MongoDB provides a query language designed around documents. For example, we could find courses whose title contains a particular value:

db.courses.find({
    title: "C# Fundamentals"
})

We can also query nested fields:

db.courses.find({
    "instructor.name": "John Smith"
})

Arrays can also be queried:

db.courses.find({
    "lessons.title": "Middleware"
})

MongoDB also provides an aggregation pipeline for more complex operations such as filtering, grouping, sorting, and calculating results. Indexes can be created to improve frequently used queries.

The important architectural point is that document databases are not simply storage systems for JSON. They provide querying and indexing capabilities designed around the document data model.

When Document Databases Are a Good Choice

Document databases are particularly useful when the application's data naturally forms aggregates or hierarchical objects. Product catalogs, content management systems, user profiles, course catalogs, configuration data, and many REST API workloads are good examples.

They are also useful when different records have varying attributes or when the application needs to evolve its data structure quickly. A document model can also work well when most operations retrieve an entire aggregate rather than joining many independent entities.

For example, an e-commerce product catalog may contain books, laptops, clothing, and furniture. Each category can have different attributes. A document model can represent these differences naturally without creating a large collection of nullable relational columns.

When a Document Database May Not Be the Best Choice

A document database may be less suitable when the application depends heavily on complex relationships, extensive joins, strict referential integrity, or large multi-entity transactions.

Consider a banking system containing accounts, transactions, customers, transfers, and regulatory records. The relationships and transactional requirements may make PostgreSQL or SQL Server a more natural foundation.

The decision should therefore be based on the application's data relationships, access patterns, consistency requirements, and transaction boundaries, rather than simply choosing MongoDB because it is classified as NoSQL.

Introduction to MongoDB

MongoDB is a document-oriented database designed around BSON documents. A typical architecture can contain an application, MongoDB drivers, a MongoDB cluster, replica sets, and optionally sharding for distributing data across multiple nodes.

A .NET application can connect using the official MongoDB driver:

var client = new MongoClient(connectionString);
var database = client.GetDatabase("LearningPlatform");
var courses = database.GetCollection<Course>("Courses");

var course = await courses
    .Find(x => x.Title == "C# Fundamentals")
    .FirstOrDefaultAsync();

This example shows an important characteristic of document databases: the application can work with a domain object while the database stores a document representation of that object.

Architectural Perspective

The most important concept in document databases is not JSON itself. It is the idea of designing data around the way the application uses it. You need to decide which information belongs together, which information should be embedded, which information should be referenced, and which queries need to be fast.

As we move into more advanced NoSQL topics, this idea will become increasingly important. MongoDB and other document databases provide flexibility and scalability, but good performance depends heavily on thoughtful data modeling.

The key idea is that a document database stores related information in document-shaped aggregates and gives architects greater flexibility in how data is structured. Its main strength is allowing the data model to closely match application access patterns, while its main challenge is deciding when to embed, reference, duplicate, or separate data.