Document Databases (Hierarchical Databases)
You already know how to work with MongoDB. This scriptum does not repeat the commands. It looks at document databases from the outside and answers:
- Why are document databases hierarchical databases?
- How do they keep data consistent and structured — without a fixed schema?
- What happens when MongoDB runs as a cluster (replica set)?
- How do we classify them?
1. Documents are trees
The hierarchical model is older than the relational one: IBM’s IMS (1966) stored data as trees — one parent, many children (used for the Apollo program).
A JSON document is exactly such a tree:
order 1001 {
├─ customer "_id": 1001,
│ ├─ name: Anna "customer": { "name": "Anna", "city": "Krems" },
│ └─ city: Krems "items": [
└─ items { "product": "Keyboard", "qty": 1 },
├─ Keyboard, qty 1 { "product": "Mouse", "qty": 2 }
└─ Mouse, qty 2 ]
}
| Term | Relational equivalent |
|---|---|
| database | database |
| collection | table |
| document | row — but nested |
| field | column |
| embedded document / array | separate table + foreign key |
_id | primary key |
Strength of trees: everything below one root is read and written in one piece. Weakness of trees: data that belongs to several parents (a product in many orders, a customer with many orders) does not fit naturally.
2. Structure: embedding vs. referencing
The central design decision in every document database:
| Embed | Reference | |
|---|---|---|
| Reads | one query | several queries or $lookup |
| Writes | atomic (one document) | several documents |
| Duplicates | yes | no |
| Good when | data is read together, belongs to one parent, stays small | data is shared, changes on its own, or grows without limit |
We will practise designing document structures in detail in a later block. For now it is enough to know that this decision exists and what it costs.
3. Consistency in hierarchical databases
3.1 The document is the unit of atomicity
- A write to one document is always atomic — even if it changes ten nested fields.
- That is the reason to embed: an order with its items is saved all or nothing, without a transaction.
- Since MongoDB 4.0 there are also multi-document ACID transactions — but they are slower and should be the exception.
3.2 Duplicates → update anomalies
If Anna’s name is embedded in 200 orders and she marries and changes her name:
db.orders.updateMany({ "customer.name": "Anna Berger" },
{ $set: { "customer.name": "Anna Huber" } })- 200 documents change — not atomically together (unless in a transaction).
- A reader may see some orders with the old and some with the new name.
- Sometimes this is even wanted: an invoice should show the address at the time of the order.
3.3 Structure without a fixed schema
“Schemaless” does not mean “no rules”. MongoDB can validate documents:
db.createCollection("orders", {
validator: { $jsonSchema: {
required: ["customer", "items"],
properties: {
items: { bsonType: "array", minItems: 1 }
}
}}
})- Flexible: new optional fields need no migration.
- Checked: required fields and types can still be enforced.
- Without validation, the application is responsible for consistent structure.
4. MongoDB as a cluster: the replica set
4.1 Roles
| Role | Task |
|---|---|
| Primary | the only node that accepts writes |
| Secondary | copies the primary’s oplog (operation log) asynchronously, can serve reads |
| Election | if the primary is unreachable (default: 10 s), the remaining nodes elect a new one — but only with a majority (2 of 3, 3 of 5) |
Why an odd number of nodes? With 2 nodes, losing one means no majority → no primary. 3 nodes tolerate 1 failure, 5 nodes tolerate 2.
4.2 How safe is my write? Write concern
| Write concern | The write is confirmed when … | Risk |
|---|---|---|
w: 1 | the primary has it | lost if the primary crashes before replicating |
w: "majority" (default since 5.0) | a majority of nodes has it | survives the crash of any single node |
w: 3 | all three nodes have it | write fails/hangs if one node is down |
4.3 Where do I read? Read preference
| Read preference | Reads from | Result |
|---|---|---|
primary (default) | primary only | always the latest data → CP behaviour |
secondary / nearest | a secondary | maybe stale data, but works even if the primary is gone → AP-like behaviour |
The same database can behave CP or AP — you choose per query. “MongoDB is CP” describes the default.
5. Classification: document databases
| Criterion | Document |
|---|---|
| Data model | documents (JSON/BSON trees) in collections |
| Schema | flexible, schema on read; optional validation ($jsonSchema) |
| Query language | product-specific (MongoDB Query API, aggregation pipeline) |
| Relationships | embedding (hierarchy) or references ($lookup, no foreign-key checks) |
| Transactions | atomic per document; multi-document ACID possible but costly |
| CAP (default) | CP (writes only on the primary, majority elections); AP reads possible |
| Scaling | replica sets (X-axis) + sharding by a shard key (Z-axis) |
| Strengths | natural fit for objects/JSON, fast reads of whole aggregates, flexible structure |
| Weaknesses | duplicates and update anomalies, many-to-many relationships, no referential integrity |
| Typical use | product catalogues, content management, user profiles, orders, IoT payloads |
| Examples | MongoDB, CouchDB, Firestore, Couchbase, Amazon DocumentDB |
6. Summary
- Document databases are hierarchical: every document is a tree.
- Embedding = fast and atomic, but duplicates. Referencing = no duplicates, but more queries.
- Atomicity is guaranteed per document; multi-document transactions exist but are the exception.
- Structure is flexible but can be validated with
$jsonSchema. - A replica set has one primary and several secondaries; a majority is needed to elect a primary and to confirm
w: "majority"writes → CP by default.
7. Self-check questions
- Why is a document database called a hierarchical database?
- Which old database system already used the hierarchical model?
- Name two advantages of embedding and two of referencing.
- Why do you need no transaction to save an order with all its items in MongoDB?
- What is an update anomaly? When can duplicated data even be desired?
- “MongoDB is schemaless, so the data can be anything.” — Correct this statement.
- What is the oplog?
- Why should a replica set have an odd number of members?
- Your replica set has 3 members, 2 are down. Can you still write? Can you still read?
- What is the difference between
w: 1andw: "majority"?
Short answers
- Each document is a tree: one root with nested objects and arrays (parent → children).
- IBM IMS (1966).
- Embedding: one query, atomic writes. Referencing: no duplicates, shared data can change independently.
- Because the whole order is one document, and writes to one document are atomic.
- The same fact is stored several times and only some copies are updated. Desired e.g. for an invoice address at the time of the order.
- The structure is flexible, but a collection can enforce rules with
$jsonSchemavalidation — and without it, the application must keep the structure consistent. - The operation log of the primary; secondaries replay it to copy all changes.
- So that a majority remains after failures and no tie can happen; 3 nodes tolerate 1 failure.
- No write (no majority → no primary). Reads from the remaining secondary are possible if you allow secondary reads — but maybe stale.
w: 1confirms after the primary saved it;w: "majority"waits until most nodes have it, so it survives a primary crash.