"Relational to Document" (p. 306) draws the escape: an unreadable schema, a big arrow, one document — whose contributors "Eliot Horowitz" and "Dwight Merriman" (both @10gen.com) co-founded 10gen in 2007, the company that released MongoDB in 2009 and became MongoDB Inc. in 2013 (Wikipedia).
One object, one document: the document model and how to design it
After this lesson you will read and write a MongoDB document with its types, decide for every relationship whether to embed or to reference, and answer the exam's "how many collections" question from an ER diagram.
On p. 291 Ann's order 1001 is a single card: her name, three line items and an Amex card. The relational database behind the shop keeps the same order in four tables — orders, customers, order lines, credit cards — and the slide draws six purple arrows from the card into them. Every time the order is shown again, the database walks those arrows back with joins.
A document database offers to store the card itself. Yet sixteen pages later the same deck asks a question and leaves it open: "To embed or not to imbed. That is the question!" (p. 307). If storing the card is so plainly better, why is it a question at all? And why did the exam of 30 January 2026 take away the one operator, $lookup, that would let you dodge it?
Keep both questions. The last section answers them.
One order, four tables: why a document store
"Why document-based?" The slide (p. 291) gives three reasons — "Handles Schema Changes Well (easy development)", "Solves Impedance Mismatch problem", "Rise of JSON" — and draws the second one.
Before: rows in four tables (relational)
After: one document (document store)
The impedance mismatch is the gap between the two shapes of Fig. 1: the program thinks in objects that contain lists and other objects, the relational database in flat rows linked by keys, so every read joins and every write takes the object apart (lesson 4 met it as the ORM problem). A document has the shape of the object, and it is read and written as one unit.
The first reason is change. A relational table fixes its columns; a document carries its own field names, so new documents can have one more field while the old ones keep working — "Dynamic schemas", says the overview slide (p. 293), with the data "stored in JSON-like documents". JSON, the third reason, is what web applications already exchange, so a document travels from the browser to the database almost unchanged.
Why is one document also fast? "MongoDB is fast and scalable" (p. 295) answers with a picture, "Better data locality". Its other two panels, in-memory caching and the distributed architecture, belong to lesson 16.
MongoDB belongs to the first of the four NoSQL families the deck opens with — "Document", "Graph", "Key-value", "Wide-column" (p. 286), compared in lesson 5. Of the nine tiles of its own pitch (p. 294), this lesson is about one: the "Rich data model".
A document stores an object the way the application uses it: one unit, one read, no join to rebuild it.
Database, collection, document, field — and the _id
The exercise session defines the containers in four sentences (p. 1416): "MongoDB is a document-oriented database that stores data within Collections of Documents. Documents consist of a set of key-value pairs, which are the basic unit of data in MongoDB. Collections contain sets of documents. Databases are made by one or more collections." Fig. 3 puts the next two slides together.
The lecture's own table (p. 297) has eight rows. Six only translate words. Two do more, and they are the subject of this lesson and of lesson 15:
| SQL Terms/Concepts | MongoDB Terms/Concepts |
|---|---|
| database | database |
| table | collection |
| row | document |
| column | field |
| index | index |
| table joins (e.g. select queries) | embedded documents and linking |
| Primary keys | _id field is always the primary key |
| Aggregation (e.g. group by) | aggregation pipeline |
Read the sixth row twice: the join is not replaced by a faster join but by a design decision — embed the related data or link to it (section 4).
A collection is a bag of documents (p. 302): the slide's three cards share their fields, but nothing forces them to. A field holds "Native data types", "Arrays" or "Other documents" (p. 303) — the last item, documents inside documents, is what makes embedding possible. Under the list, one rule: "Rule: Every document must have an _id."
The _id identifies the document in its collection. If you supply none, MongoDB creates an ObjectId (p. 1420): "The 12-byte ObjectId value consists of three different elements" — "A 4-byte timestamp value, representing the value creation, measured in seconds since the Unix epoch", "A 5-byte random value generated once per process", "A 3-byte incrementing counter, initialized to a random value". In the session's ObjectId("5ea64532a7678a3b27d34e00"), 24 hexadecimal digits for 12 bytes, 5ea64532 is the time, a7678a3b27 the random value, d34e00 the counter. The random part and the counter let two programs create ids at the same moment without asking anybody; the time in front keeps ids roughly in creation order. Other values work too: "First Post" on p. 309, integers on p. 312, the key "12345" on p. 1443.
The session's sample document (p. 1419) labels the kinds of value you will write in every design answer:
| Field | Value | Label on the slide | In a relational design |
|---|---|---|---|
_id | ObjectId("5ea6…4e00") | ObjectId | the primary key |
name | {"first": "Mark", "last": "Jonhson"} | Complex Structure - Sub-document | two columns |
age | 37 | Simple Field | a column |
birth_date | {"$date": "1986-03-01T00:…"} | Complex Field | a date column |
address | {"street": …, "city": "Milan", …} | Complex Structure - Sub-document (p. 1423) | columns, or a one-to-one table |
mobile_phone_numbers | [{…, "Wind"}, {…, "TIM"}] | Complex Structure - Sub-Collection | a separate table with a foreign key |
Keep the session's words: a sub-document is one embedded object, a sub-collection an array of sub-documents — what the papers mean by "Perform the query starting from the Chef Collection or Sub-Collection" (exam of 6 Sep 2024). The {"$date": …} is how tools display a BSON date; in an answer write ISODate("1986-03-01"). Dot notation reaches inside both (p. 1423): "address.city" names one value, "mobile_phone_numbers.service_provider" one value per element of the array — the main trap of lesson 14.
A document enters a collection with insertOne (p. 1421), and the _id is added for you:
// p. 1421: adds one document; MongoDB generates its _id
db.people_collection.insertOne({
"name": {"first": "Mike", "last": "Ruby"},
"age": 63
})
It comes back with find (every match), findOne (the first) or, as a number, countDocuments (p. 1424). The filter is itself a document, here with two dotted fields:
// p. 1424: returns every document whose name is Mark Jonhson
db.people_collection.find(
{"name.first": "Mark", "name.last": "Jonhson"}
)
The same slides create an index (p. 1422) — fields with 1 for ascending or -1 for descending — and print its price: "Faster Queries and Improved Read Performance but Slower Writes and Increased Storage". Filters and indexes are lesson 14's.
// p. 1422: a compound index on three fields
db.people_collection.createIndex(
{"name.last": -1, "name.first": 1, "age": 1}
)
JSON on the screen, BSON on the disk
"What is a document?" (p. 292) answers with a record from a business directory rather than with a definition:
// p. 292 (and p. 308): one business, one document
{
"business_id": "rncjoVoEFUJGCUoC1JgnUA",
"full_address": "8466 W Peoria Ave\nSte 6\nPeoria, AZ 85345",
"open": true,
"categories": ["Accountants", "Professional Services",
"Tax Services"],
"city": "Peoria",
"review_count": 3,
"name": "Peoria Income Tax Service",
"neighborhoods": [],
"longitude": -112.241596,
"state": "AZ",
"stars": 5.0,
"latitude": 33.581867000000003,
"type": "business"
}
Read it as a list of types: strings, a boolean, an integer, floating-point numbers, an array of strings, an empty array ("neighborhoods": [] exists and holds nothing), newlines escaped inside a string. A document is typed, nested and self-describing: every value travels with its field name.
The JSON slide (p. 300) gives the syntax in five bullets: "Data is in name / value pairs", each pair "a field name followed by a colon, followed by a value", "Data is separated by commas", "Curly braces hold objects", "An array is stored in brackets []". Its last example, two Star Wars characters of which only R2-D2 has a race, is section 4's polymorphism in miniature.
"Quoting field names is optional." In the shell, yes — it is JavaScript, and the slide itself leaves race bare (p. 300). In JSON, no. Quote every name in an exam answer, as the exercise session does: the document is then valid both ways.
MongoDB does not keep the text: "Data stored as BSON (Binary JSON)", "used for speed", "translation handled by language drivers" (p. 299). The BSON slide (p. 301) says what is inside: "Each entry consists of a field name, a data type, and a value", and "Files and large elements in a BSON document are prefixed with a length field to facilitate scanning". Fig. 4 encodes the first two fields of the document of p. 303, byte by byte.
{ name: "sue", age: 26 }, the first two fields of p. 303, as BSON (encoded with the official driver library: 28 bytes). Violet: what BSON adds — the total length, a type byte before each field (string, then 32-bit integer), the string's own length and the end byte. Blue: the values. The same data as JSON text, {"name":"sue","age":26}, has 23 characters.The 28 bytes, one by one
| Bytes (hex) | How many | Meaning |
|---|---|---|
1c 00 00 00 | 4 | total length: 28, written as a 32-bit integer, lowest byte first |
02 | 1 | type of the next field: string |
6e 61 6d 65 00 | 5 | the field name "name" and an end byte |
04 00 00 00 | 4 | length of the string: 4 (s, u, e and its end byte) |
73 75 65 00 | 4 | "sue" and its end byte |
10 | 1 | type of the next field: 32-bit integer |
61 67 65 00 | 4 | the field name "age" and an end byte |
1a 00 00 00 | 4 | the value 26 |
00 | 1 | end of the document |
The bytes explain the slide. A reader looking for age reads the type and name of the first field, finds the string's length, 4, and jumps over the value: that is "to facilitate scanning", and why BSON is "used for speed". The same slide says "Optimized for space and speed"; Fig. 4 shows that space is a goal, not a promise — speed is the sure gain. And every value has a type: "BSON types are a superset of JSON types (JSON does not have a date or a byte array type, for example), with one exception of not having a universal "number" type as JSON does." Where JSON has one number, BSON picks a 32-bit integer like the 26 above, a 64-bit integer or a double: the integer 1 and the double 1.0 are two BSON types, although a query compares them by value.
"Facts (1)" (p. 298) sets the ceiling: "Max docuement size of 16MB", "Larger documents handled with GridFS". The server counts 16 MB as 16,777,216 bytes and refuses a bigger insert ("object to insert too large"); GridFS stores files such as videos in chunks over several documents (background). For design, the cap warns against arrays that never stop growing.
The security slide (p. 296) adds "SSL" ("between client and server", "Intra-cluster communication") and "Authorization at the database level": "Read Only/Read+Write/Administrator". In January 2017 about 10,500 MongoDB databases open to the internet, with no administrator password, were wiped and held for ransom within days (BleepingComputer, 7 January 2017): authorization works only when it is switched on.
Embed or reference: the one design decision
The same user, two ways: on p. 304 one document with two "Embedded sub-document"s, contact and access; on p. 305 three documents — "Reference documents or linking documents" — where contact and access point back to the user through user_id, the user's _id.
Embedded: one document (p. 304)
Referenced: three documents (p. 305)
_id is boxed on the slide as "The primary key". Right (p. 305): three documents; contact and access carry user_id, the user's _id (highlighted) — a reference that the application follows with a second query.An embedded document is read with its parent in one fetch and written with it in one operation. A reference is only a field holding another document's _id: MongoDB neither checks that the target exists, as a foreign key would, nor follows it in a find — the application sends a second query. It can sit on either side: on p. 305 each child holds its parent's id, on p. 1444 the parent holds an array of its children's ids, "orders": [ "order1", "order2" ]. The course notes warn that overusing references "would be just like recreating a relational database" (notes, 3.5.2).
"Designing NoSQL Data Structures" (p. 307) gives the method: "NoSQL data structures driven by application design", "Need to take into account necessary CRUD operations", "To embed or not to imbed. That is the question!", "Rule of thumb is to imbed whenever possible" — and, for whoever hoped for a recipe, "No modeling standards or CASE tools!" Design starts from what the application reads and writes. The deck shows three structures:
// p. 309: a post with its comments, one document
{
"_id": "First Post",
"comments": [
{"author": "Bob", "text": "Nice Post!"},
{"author": "Tom", "text": "Dislike!"}
],
"comment_count": 2
}
"A (denormalized) embedded structure": an array of values on p. 308 (the categories of the business above) or an array of sub-documents on p. 309 — a one-to-many folded into the parent and read in one go. comment_count repeats the array's length on purpose: a denormalized counter that makes "posts with more than two comments" a plain comparison, at the price of updating it with each comment.
// p. 310: two collections, post and comments
// db.post
{
"_id": "First Post",
"author": "Rick",
"text": "This is my first post."
}
// db.comments
{
"_id": ObjectId("..."),
"post_id": "First Post",
"author": "Bob",
"text": "Nice Post!"
}
"A normalized structure": each comment is a document of its own, pointing to its post through post_id. A post with its comments costs two queries; in exchange, comments can be found, edited or paged on their own, and the post never grows.
// p. 312: two kinds of document in one collection, nodes
// Page document
{
_id: 1,
title: "Welcome",
url: "/",
type: "page",
text: "Welcome to my wonderful wiki."
}
// Photo document
{
_id: 3,
title: "Cool Photo",
url: "/photo.jpg",
type: "photo",
content: Binary(...)
}
"A polymorphic structure" (p. 311): "When all the documents in a collection are similarly, but not identically, structured." The shared fields are _id, title, url and type, which tells the application which shape to expect; text and content (binary data, a type JSON lacks) belong to one kind each. The gains: "Enables simpler schema migration", no spare columns like "custom_field_1" ("no more of this crap"), and "Better mapping of object – oriented inheritance and polymorphism". Section 5 stores ISA hierarchies this way.
As a default the rule of thumb is right. Four situations — call them the four stop signs — make it a mistake:
- Size and growth. An array that grows forever — sensor readings, a customer's orders — drifts towards the 16 MB of p. 298, and each new element rewrites a bigger document.
- Duplication. Data embedded in many parents is copied into each; a change must find every copy.
- Many-to-many. The shared side of an M:N relationship is such data: one product in thousands of orders.
- Independent access. An entity read or updated on its own — a product page — needs its own collection.
The exercise session says it in two lines (p. 1444): "If related data is often queried together, embed it directly in the document"; "If related data is large or accessed independently, store references instead of embedding". The widget tests the four signs on the invoice of lesson 9.
Embed what is read together, stays bounded and belongs to one parent; reference what grows, is shared or is read on its own.
From ER diagram to documents: the session's recipe
The exercise session turns these principles into rules for the diagram every exam starts from (pp. 1443–1450). Entities first: "Entities become collections", "Each collection stores documents representing instances of the entity", and "Attributes of an entity are represented as fields within a document" (p. 1443):
// p. 1443: one entity, one collection
db.createCollection('user');
{
"_id": "12345",
"name": "John Doe",
"email": "john.doe@example.com",
"age": 30
}
Relationships change that. For a one-to-many, p. 1449: "Nest the entity on the N side inside the entity on the 1 side." and "You don't need to create a reverse link by nesting the 1-side entity inside each N-side document."
// p. 1449: the books (N side) inside their author (1 side)
{
"_id": ObjectId("..."),
"name": "J.K. Rowling",
"books": [
{ "title": "Harry Potter and the Sorcerer's Stone",
"year": 1997 },
{ "title": "Harry Potter and the Chamber of Secrets",
"year": 1998 }
]
}
Which side is N? Read the pairs as lesson 6 taught (read it from the right side): the pair next to an entity counts the partners of one of its instances. Author (1,N) — Writes — (1,1) Book: an author writes one to many books, a book has exactly one author, so Book is the N side and the books go inside the author. For the papers: nest the entity next to (1,1) inside the entity next to (1,N).
"Nesting the other way round is just as good." It copies the 1 side into every N-side document and loses the instances without a partner: with Customer (0,N) — places — (1,1) Order, a customer who has not ordered yet has no document (try it in the widget above). Likewise an N-side instance that may lack a parent, (0,1), cannot be nested.
For a many-to-many, p. 1450: "Modeled using reference IDs" — arrays of ids, on both sides in the slide's example — "Or separate linking collections":
// p. 1450: Student (M:N) Course with reference ids
db.createCollection('student');
{
"_id": ObjectId("..."),
"name": "Alice",
"enrolledCourses": [ ObjectId("course1"), ObjectId("course2") ]
}
db.createCollection('course');
{
"_id": ObjectId("course1"),
"title": "Database Systems",
"students": [ ObjectId("student1"), ObjectId("student2") ]
}
// p. 1450: the same relationship as a linking collection
db.createCollection('enrollment');
{
"studentId": ObjectId("student1"),
"courseId": ObjectId("course1"),
"enrolledOn": "2025-09-01"
}
The linking document is the natural home of a relationship's own attribute: enrolledOn belongs to the pair (student, course), not to either side. The exam diagrams are full of them — Role on Works For, Since on Play, Production Date on Produce — and wherever the pair ends up, the attribute goes with it.
ISA hierarchies get one slide for each letter of the pair you met in lesson 6 (pp. 1445–1448). Total, "must be": "Only the child entities are converted into documents. Each child includes its own attributes plus inherited ones from the parent." Partial, "may be": "Both parent and child entities are transformed into documents." Exclusive, "not both": "Each child entity becomes a separate document." Overlapping, "also both": "A document may contain attributes from multiple child entities involved in the hierarchy." In all four the documents go into one collection, person — the polymorphic structure of p. 311. The other group's summary (p. 1469) adds, under partial, the case of a hierarchy nested inside another document: "These can be managed either with a single or multiple sub-collections when nested".
// after p. 1445 (total): only children, distinct _ids
db.createCollection('person');
// Instance of a student
{ "_id": "p1", "name": "John Doe", "fee": 1000 }
// Instance of a professor
{ "_id": "p2", "name": "Jane Roe", "salary": 1400 }
| In the ER diagram | In MongoDB | Page |
|---|---|---|
| entity | a collection, one document per instance | 1443 |
| attribute | a field of the document | 1443 |
| any relationship | embed if queried together; reference if large or accessed independently | 1444 |
| 1:N | the N side nested in the 1 side as a sub-collection; no reverse link | 1449 |
| M:N | arrays of reference ids, on one or both sides, or a linking collection | 1450 |
| attribute of a relationship | in the linking document; when the pair is embedded, inside the embedded element (our reading) | 1450 |
| ISA total / partial | only child documents / parent and child documents | 1445–1446 |
| ISA exclusive / overlapping | one child's attributes per document / several children's | 1447–1448 |
| ISA inside another document | one sub-collection, or one sub-collection per child (printed under partial; open to a total hierarchy too, our reading) | 1469 |
The exam's design question, solved
Every past paper opens its MongoDB exercise with a design question on a few entities of the ER diagram. Most papers of 2025 ask: "How many collections would you define within a documental database (clearly state it)? How would you implement the relations between the concepts? Provide a simple documental representation. (1 PT)" The exam of 11 Feb 2025 adds "specifying all attributes and their types or an example" and "Do not include any attributes besides the ones in the ER model", and leaves a blank: "NUMBER OF COLLECTIONS: ______ ← HERE!". The paper of 30 January 2026 rewords it and gives it 2 points: "How would you implement the nesting of the entities and the relationships between them? Provide a simple documental representation. Define ALL attributes and their types, and provide additional comments when needed. You must design the relationships without using the MongoDB $lookup operation."
$lookup is the aggregation stage that joins two collections. The practical lectures never teach it, and the ban spells out the consequence: every query runs on one collection, so each document must contain everything the queries read. Here is that paper, exercise 3, step by step.
The scenario: "a hospital heating management system". The entities asked are Hospital (Hospital_ID, Name), Building (Building_ID, Name, Year), Department (Department_ID, Specialty, N_Beds, Head_Physician_ID) and Person (P_ID, Email), related as in Fig. 6. The queries printed below the design ask, "for each hospital with more than 10 buildings, the number of departments with more than 25 people", and "the total number of departments each person with the role 'maintenance' works for".
Before: the four entities and their relationships
After: one document per hospital
Keep only the entities asked. Hospital, Building, Department, Person. Floor and the heating systems are on the diagram but not in the question: they stay out.
List their relationships with the pairs. Has Building and Has Dept. have 1:N next to Hospital and 1:1 next to Building and Department: one-to-many. Works For has 1:N on both sides: many-to-many, with Role.
Nest the N sides (p. 1449). Building and Department become the sub-collections
buildingsanddepartmentsof the hospital document, with no reverse link.Place the many-to-many by the queries. The slide offers reference ids or a linking collection (p. 1450), but without
$lookupa query on departments cannot reach people stored elsewhere. So each department carries its people, and Role goes inside each person entry, because it belongs to the pair.Count and type. One collection,
hospital. The ER key becomes_id; every attribute appears once, with its type.Check against the queries. Buildings per hospital, people per department, the Role of each person entry: all inside one document, no join needed. (The pipelines are lesson 15's.)
// NUMBER OF COLLECTIONS: 1 (hospital)
db.createCollection('hospital');
{
"_id": "H01", // Hospital_ID: String
"Name": "Ospedale Nord", // String
"buildings": [ // Has Building (1:N)
{ "Building_ID": "B01", // String
"Name": "Pavilion A", // String
"Year": 1968 } // Integer
],
"departments": [ // Has Dept. (1:N)
{ "Department_ID": "D07", // String
"Specialty": "cardiology", // String
"N_Beds": 40, // Integer
"Head_Physician_ID": "P042", // String
"people": [ // Works For (M:N)
{ "P_ID": "P042", // String
"Email": "p042@nord.it", // String
"Role": "head physician" // String, of Works For
}
] }
]
}
The comments the paper asks for: Building and Department are nested because each belongs to one hospital; a person working for three departments appears three times, Email included — accepted, so that both queries run on one collection. A second collection person (P_ID, Email), with only P_ID and Role in the departments, would also work and store each Email once: say which you chose, and why. Both queries of the paper were run on this design on a real MongoDB server, without $lookup.
Read the queries first. They are printed right under the design question, and they tell you the root of your documents ("for each hospital…") and every entity that must be reachable from it by nesting.
What a complete answer shows — our reading, since no solutions are published: the number of collections, stated; every ER attribute with its type, none invented; each relationship placed and named in a comment; the duplication acknowledged; documents on which the paper's queries run without $lookup.
Back to the hook. Storing the card is right when the pieces are read together, stay bounded and belong to this one order — true of the line items and the payment details, not of Ann, who orders for years, nor of the products, each in thousands of orders. That is why the slide's rule stops at "whenever possible": "to embed or not to imbed" is answered per relationship, by the four stop signs. With $lookup banned it becomes the exam's question: no query may join, so you nest along the queries and copy, with a comment, what a many-to-many shares.
Exam-style questions
Four theory questions in the form of the theory part — open answers of a few sentences, and closed ones where a wrong tick may cost points — and two design questions from past papers. The MongoDB exercise always starts from the paper's ER diagram; its design sub-question was worth 1 point in the 2024–2025 papers and 2 in the paper of 30 January 2026.
Explain why document-based databases were introduced. Describe the impedance mismatch problem with an example and explain how a document store addresses it.
Show model answer
The lecture gives three reasons: document databases handle schema changes well (easy development), they solve the impedance mismatch problem, and they follow the rise of JSON. The impedance mismatch is the difference between the shape of the data in the application and in a relational database. In the program an order is one object with a customer, a list of line items and payment details; in a relational database it is split over the tables orders, customers, order lines and credit cards, so every read must join the tables and every write must take the object apart. A document store keeps the order as one JSON-like document, with the line items as an array of sub-documents and the payment details as an embedded sub-document. The object is read and written as a unit, with one fetch and no join, and its data is stored together (better data locality). Since a collection does not impose a schema, new documents can carry new fields without changing the old ones.
A complete answer has three parts: the three reasons in the slide's words, a concrete object split over several tables, and the mechanism of the cure (embedding, one read). The order of p. 291 is the example the slide itself draws.
Which statement about BSON is correct according to the lecture?
Show model answer
BSON types are a superset of JSON types, with the exception of not having a universal "number" type as JSON does. BSON is a binary serialization of JSON-like documents: each entry has a field name, a data type and a value, and large elements are prefixed with their length to speed up scanning.
A closed question that quotes p. 301 almost word for word. Wrong ticks may be penalised: the "always more compact" option is the tempting one, and Fig. 4 shows why it is false.
A document has "_id": ObjectId("5ea64532a7678a3b27d34e00"), generated by MongoDB. Which statements are correct? Select all that apply.
Show model answer
The first, second and fourth statements. An ObjectId is the default value of the mandatory _id field, the primary key of the collection. It has 12 bytes: a 4-byte timestamp (seconds since the Unix epoch), a 5-byte random value generated once per process, and a 3-byte incrementing counter initialised to a random value.
Three correct options of five. Wrong ticks may be penalised, so tick only what you can justify from p. 1420 and p. 297.
Explain the difference between embedding and referencing documents in MongoDB, and give one situation in which each is preferable.
Show model answer
Embedding stores the related data inside the document, as a sub-document or an array of sub-documents — for example the contact and access data inside the user, or the comments inside a post. One read returns everything, without a join, and the whole document is written in one operation. Referencing stores in one document the _id of another document, which lives in its own collection — for example user_id in a contact document, or post_id in a comment. The database does not enforce the reference and does not follow it: the application needs a second query. The lecture's rule of thumb is to embed whenever possible; the exercise session says to embed data that is often queried together and to reference data that is large or accessed independently. The line items of an order are always shown with the order and belong only to it, so they are embedded. A product appears in many orders and has its own catalogue page, so it is referenced by its id: embedding it would copy it into every order, and every price change would have to update all the copies.
A complete answer gives the two definitions, the cost of each (second query against duplication and growth), the rule of thumb and a pair of situations that follow from the criteria. Naming the 16 MB limit as the reason not to embed unbounded arrays is a good addition.
Exam of 13 Jun 2025 (its header prints Jan. 21, 2025), exercise 3. ER scenario: a data structure for tracking concert attendances and performances. Person (Personal ID, Name, Surname, Birth Date) has the children Audience, Artistic Director, Maestro (Biography, Stage Name) and Musician (Biography), (T, E). Orchestra (Name, Foundation Date, Biography). Instrument (Name, Type (e.g., chordophones), Description). Maestro (1,1) — Direct — (1,1) Orchestra, with First Concert (Yes/No); Orchestra (10,N) — Compose — (1,2) Musician; Musician (1,N) — Play — (1,N) Instrument, with Since.
Consider the entities Orchestra, Maestro, Musician, and Instrument. How many collections would you define within a documental database (clearly state it)? How would you implement the relations between the concepts? Provide a simple documental representation. (1 PT)
Show model answer
NUMBER OF COLLECTIONS: 1 — orchestra. Direct is one-to-one, so the maestro is an embedded sub-document with First_Concert inside it. Compose is many-to-many, but a musician plays in at most two orchestras: the musicians are embedded as a sub-collection of each orchestra, and a musician is copied at most twice. Play is many-to-many with Since: the instruments are embedded in each musician, with Since inside each entry. Person is (T, E), so maestros and musicians carry Person's attributes plus their own, and there are no bare persons.
db.createCollection('orchestra');
{
"_id": "Orchestra Aurora", // Name: String
"Foundation_Date": ISODate("1982-01-01"),
"Biography": "...", // String
"maestro": { // Direct (1:1)
"Personal_ID": "P001", // String
"Name": "Claudio", // String
"Surname": "Neri", // String
"Birth_Date": ISODate("1960-05-05"),
"Biography": "...", // String
"Stage_Name": "Maestro Neri", // String
"First_Concert": true // Boolean, of Direct
},
"musicians": [ // Compose (M:N, max 2)
{ "Personal_ID": "P101", // String
"Name": "Fabiana", // String
"Surname": "Rossi", // String
"Birth_Date": ISODate("1994-02-11"),
"Biography": "...", // String
"instruments": [ // Play (M:N)
{ "Name": "piano", // String
"Type": "chordophones", // String
"Description": "...", // String
"Since": ISODate("2010-09-01") } // Date, of Play
] }
]
}
The paper's queries — musicians named "Fabiana" who play the piano, members per orchestra and instrument, orchestras directed by "Claudio" with a member "Lorenzo" who plays the piano — all start from orchestras and run on this one collection, as a run on a real server confirmed. One consequence to say in the comments: since a musician can be stored in two orchestras, a count of musicians must count distinct Personal_IDs.
Exam of 30 May 2025 (its header prints June 30, 2025), exercise 5. ER scenario: a data structure for tracking puzzles' production and sales. Company (Code, Name, Address, Phone Number, Biography); Puzzle (Puzzle ID, Name, Collection Name, Number of Pieces, Width, Height, Description); Frame (Frame ID, Width, Height, Material, Color); Image (Title, Width, Height, Description) with the child Painting (Artist Name, Artist Surname, Painting Location), (P, E). Company (1,N) — Produce — (1,1) Puzzle, with Production Date; Image (1,N) — Based — (1,1) Puzzle; Puzzle (1,N) — Fit — (1,N) Frame. All sizes are in cm.
Consider the entities Puzzle, Image, Frame, and Company. How many collections would you define within a documental database (clearly state it)? How would you implement the relations between the concepts? Provide a simple documental representation. (1 PT)
Show model answer
NUMBER OF COLLECTIONS: 2 — company and frame. Puzzle is the N side of two one-to-many relationships, Produce and Based, and can be nested in only one parent: it is nested in its company, with Production_Date inside each puzzle. The image a puzzle is based on is embedded in the puzzle as a sub-document; an image used by several puzzles is copied, which is accepted because an image has few attributes and the queries filter puzzles by their image. Painting is (P, E): the painting attributes appear only when the image is a painting. Fit is many-to-many: each puzzle stores the ids of its frames, and the frames are stored once in their own collection.
db.createCollection('company');
{
"_id": "C01", // Code: String
"Name": "Tessera Puzzles", // String
"Address": "Via Roma 10, Pavia", // String
"Phone_Number": "+39 0382 555 010", // String
"Biography": "...", // String
"puzzles": [ // Produce (1:N)
{ "Puzzle_ID": "PZ001", // String
"Name": "Mona Lisa 1000", // String
"Collection_Name": "Museum Collection",
"Number_of_Pieces": 1000, // Integer
"Width": 70, "Height": 50, // Number (cm)
"Description": "...", // String
"Production_Date": ISODate("2001-03-15"),
"image": { // Based: one per puzzle
"Title": "Mona Lisa", // String
"Width": 53, "Height": 77, // Number (cm)
"Description": "...", // String
"Artist_Name": "Leonardo", // Painting only
"Artist_Surname": "da Vinci", // Painting only
"Painting_Location": "Louvre" }, // Painting only
"frames": ["F01", "F07"] } // Fit (M:N): frame ids
]
}
db.createCollection('frame');
{
"_id": "F01", // Frame_ID: String
"Width": 75, "Height": 55, // Number (cm)
"Material": "wood", // String
"Color": "black" // String
}
The trap of this diagram is the puzzle with two "1" sides. Choose the parent from the queries — the first counts puzzles per company — and embed the other. The second query counts distinct frames per puzzle of a Leonardo da Vinci painting in the Louvre: it needs only the frame ids, so it runs on company alone (both queries were run on a real server). Copying the frames into each puzzle would also work: say which you chose and why.
Check yourself
A blog shows each post with all its comments. A comment is never shown or edited on its own, and posts rarely get more than fifty. Which design follows the lecture's rule of thumb?
Which of these are reasons to reference rather than embed? Select all that apply.
The session's two lines (p. 1444) contain all four stop signs: "large" is growth, "accessed independently" is access alone, and duplication and M:N are what "embed everything" costs.
The diagram says Author (1,N) — Writes — (1,1) Book. Following the session's recipe, where do the books go?
An ISA hierarchy Person → Student (fee), Professor (salary) is marked (T, E). Which documents must not appear in the person collection? Select all that apply.
T/P decides whether a parent-only document may exist; E/O decides whether one document may carry two children's attributes.
Why does MongoDB store documents as BSON rather than as JSON text?
In the paper of 30 January 2026, Works For links Department and Person (1:N on both sides) and has the attribute Role, and $lookup is banned. Where does Role go?
On p. 309 the post has "_id": "First Post". What does that show?
Key take-aways
- Document stores keep an object as the application sees it. The slide's three reasons are schema changes handled well, the impedance mismatch solved, and the rise of JSON (p. 291); data locality makes one document one read (p. 295).
- A database holds collections, a collection holds documents, a document holds fields (pp. 1416–1418; p. 297: table, row, column). A field's value is a native type, an array or another document (p. 303). Every document has an
_id, the primary key; by default a 12-byte ObjectId — 4-byte timestamp, 5-byte random value, 3-byte counter (p. 1420). - Documents are stored as BSON: field name, type and value per entry, lengths in front, types a superset of JSON's except the single number (pp. 299–301). A document may not exceed 16 MB; files go to GridFS (p. 298). The slide's "No Schemas", "No transactions", "No joins" are dated:
$lookupand multi-document transactions exist. - Embedding puts related data inside the document (one read); referencing stores another document's
_id(a second query, no enforcement) (pp. 304–305). The deck's structures are embedded (array of values, array of sub-documents), normalized and polymorphic (pp. 308–312). - "Rule of thumb is to imbed whenever possible" (p. 307) — until a stop sign: growth towards 16 MB, duplication, many-to-many, independent access. The session: embed what is queried together, reference what is large or accessed independently (p. 1444).
- The recipe: entity → collection, attribute → field; 1:N → nest the N side in the 1 side, no reverse link; M:N → reference ids or a linking collection; ISA total/partial and exclusive/overlapping decide which document shapes exist, in one collection (pp. 1443–1450, 1469). At the exam: state the number of collections, type every attribute, comment the duplication, and with
$lookupbanned, nest along the queries.
What to watch and read
-
MongoDB in 100 Seconds
Fireship
Documents, collections and the pitch "data that is accessed together is stored together" — a mental picture before any syntax.
-
Introduction to NoSQL
Martin Fowler, GOTO 2012
The first twenty to thirty minutes: the impedance mismatch and the "aggregate", the unit that is read and written together — the idea Fig. 1 rests on. Fowler co-wrote NoSQL Distilled, the book the deck recommends.
-
JSON Crack
online JSON viewer
Paste the embedded post of p. 309 and then the two normalized documents of p. 310: one tree against two separate trees, and a reference that is only a string pointing nowhere in the picture.
-
Document relationships
MongoDB manual
One-to-one, one-to-many embedded or referenced, many-to-many, each shown as documents before and after — the official version of pp. 1449–1450, plus the growth criterion the slides leave out.
-
6 Rules of Thumb for MongoDB Schema Design
MongoDB blog
One-to-few, one-to-many, one-to-squillions: a vocabulary that makes the embedding decision mechanical, and the same stop signs in the vendor's own words.