Skip to main content

Introduction

Data models are one of the most important parts of developing software, because they have such a profound effect on how we think about the problem we’re solving and how we write the software. Each layer hides the complexity of the layers below by providing a clean data model. These abstractions allow different groups of people to work together effectively. This chapter explores the most important data models for data-intensive applications:
  • Relational model (SQL)
  • Document model (NoSQL)
  • Graph model

1. Relational model vs document model

The relational model

Proposed by Edgar Codd in 1970, the relational model organizes data into relations (tables), where each relation is a collection of tuples (rows). Key characteristics:
  • Data organized in tables with fixed schema
  • Relationships represented by foreign keys
  • Queries use SQL (Structured Query Language)
  • ACID transactions for consistency
Example schema:

The document model

Document databases (MongoDB, CouchDB) store data as self-contained documents (usually JSON or XML). Key characteristics:
  • Data stored as documents (JSON, BSON, XML)
  • Schema flexibility (schemaless or schema-on-read)
  • Related data often embedded in same document
  • Natural fit for hierarchical data
Example document:

Comparison: Relational vs document

One-to-many relationships

Relational approach: Use foreign keys and joins
Document approach: Embed related data

Many-to-one and many-to-many relationships

Problem: Many entities reference the same data (e.g., many users in same city) Relational advantages for many-to-one:
  • No duplication: City name stored once
  • Consistency: Update city name in one place
  • Type safety: Can enforce valid cities
  • Easy updates: Rename city affects all users
Document challenges for many-to-one:
  • Duplication: “San Francisco” stored in many documents
  • Inconsistency risk: Some docs might have “SF”, others “San Francisco”
  • Hard to update: Must update all documents
Many-to-many relationships are even more challenging for documents, often requiring either denormalization with duplication or references (which reduce the benefits of document storage).

Schema flexibility

Schema-on-write vs schema-on-read Example: Adding a new field Relational (schema-on-write):
Document (schema-on-read):
Use schema-on-write when all documents have the same structure and you need strong consistency guarantees. Use schema-on-read when data structure varies or you need rapid iteration with frequent schema changes.

2. Query languages

Declarative vs imperative

Example: Get all users in California Imperative approach (JavaScript):
Declarative approach (SQL):
Why declarative is better:
  • Database can choose optimal execution plan
  • Can use indexes automatically
  • Can parallelize execution
  • More concise and clear
  • Less room for bugs

SQL (Structured Query Language)

SQL is the dominant declarative query language for relational databases. Common SQL patterns:

MapReduce

MapReduce is a programming model for processing large datasets in parallel. Example: Count posts per user SQL approach:
MapReduce approach (MongoDB):

Aggregation pipeline

Modern document databases offer aggregation pipelines as a middle ground. Example: Average post length per user

3. Graph databases

Some applications have data that’s more naturally modeled as a graph: nodes (entities) and edges (relationships).

Property graphs

In the property graph model:
  • Each node has:
    • Unique identifier
    • Set of outgoing edges
    • Set of incoming edges
    • Collection of properties (key-value pairs)
  • Each edge has:
    • Unique identifier
    • Starting node (tail vertex)
    • Ending node (head vertex)
    • Label to describe relationship
    • Collection of properties
Example in Cypher (Neo4j query language):

Graph queries

Graph databases excel at traversing relationships. Example queries:

Graph queries in SQL (for comparison)

The same queries in SQL require complex recursive queries:
Graph databases excel at complex traversal queries, but they may not be the best choice for simple CRUD operations or when you need strong ACID transactions across the entire database.

When to use graph databases

Graph DB use cases:
  • Social networks: Friends, followers, connections
  • Recommendation engines: Related products
  • Fraud detection: Transaction patterns, networks
  • Knowledge graphs: Entities and relationships
  • Network topology: IT infrastructure, dependencies
When graphs excel:
  • Many-to-many relationships
  • Variable depth traversals
  • Relationship properties matter

4. Choosing a data model

Real-world examples

Use relational when:
Use document when:
Use graph when:

Summary

Data models are perhaps the most important abstraction in software development. Key takeaways:
  • Start with the data model that most naturally fits your data
  • Many applications use multiple databases (polyglot persistence)
  • The data model shapes how you think about the problem
  • Consider access patterns, not just data structure
  • Schema flexibility vs. data integrity is a key trade-off
Relational: Structured data with complex queries and strong consistency requirementsDocument: Hierarchical or evolving data where related information is accessed togetherGraph: Highly connected data with complex relationship queries and variable-depth traversals