Unit 3: Schema Design and Data Modeling
I. Foundations of MongoDB Data Modeling
MongoDB is a document-oriented NoSQL database in which data is stored as BSON documents inside collections. Unlike relational modeling, which usually begins with normalized tables and joins, MongoDB modeling begins with application access patterns: what data is read together, updated together, and expected to grow together.
Defining characteristics:
- Document model: A document contains field-value pairs and may include arrays, nested documents, dates, object identifiers, and other BSON types.
- Flexible structure: Documents in one collection may have different fields or data types unless validation rules restrict them.
- Aggregate orientation: Related information can be stored as one self-contained document, making the document an application-level aggregate.
- Access-pattern design: A schema is shaped around frequent queries, writes, updates, and transactions rather than abstract normalization alone.
- Controlled denormalization: Data may be duplicated to reduce joins and improve read performance, provided synchronization costs remain manageable.
- Atomicity boundary: A write affecting one document is atomic. Multi-document transactions are available, but good modeling minimizes unnecessary dependence on them.
- Practical limits: A BSON document has a maximum size of 16 MiB, so indefinitely growing arrays or embedded histories require alternative designs.
- Relationship choices: Associations are represented primarily through embedding related data or referencing another document by its identifier.
II. Flexible Document Structure
A. Schema-less Nature of MongoDB
MongoDB is described as schema-less because a collection does not require every document to have an identical predefined structure, although applications still need an intentional logical schema.
- Structural flexibility: Documents can contain different fields according to their subtype or lifecycle stage. For example, one
productsdocument may containscreenSize, while another containsfabric. - Incremental evolution: A new field such as
loyaltyTiercan be added to new customer documents without immediately rewriting every existing document. - Polymorphic data: Different but related entities can share a collection when common fields support shared queries.
{ _id: 1, type: "book", title: "Database Systems", pages: 640 }
{ _id: 2, type: "video", title: "MongoDB Basics", durationSec: 900 }- Application responsibility: Application code must safely handle missing fields, optional values, and multiple schema versions.
- Not structure-free: Field names, BSON types, indexes, validation rules, and document relationships collectively form an implicit or explicit schema.
- Risk of inconsistency: Accidental variations such as
phoneNumber,phone_number, andphonecomplicate querying and indexing. - Design implication: Flexibility is most valuable for evolving or heterogeneous data; it should not replace governance where stable business rules exist.
III. Relationship Representation
A. Embedding vs. Referencing
Embedding stores related data inside a parent document, whereas referencing stores separate documents connected through identifiers.
-
Embedding
- Locality: Data retrieved together is placed together, allowing one query to return the complete aggregate.
- Atomic updates: Changes to embedded fields can participate in the parent document’s single-document atomic write.
- Best conditions: Embed when the child belongs exclusively to the parent, remains bounded in size, and is normally accessed with it.
- Example: An order can embed the purchased item’s name, quantity, and price because these values form an historical snapshot.
-
Referencing
- Independent identity: Related entities remain in separate collections and are connected using fields such as
customerId. - Best conditions: Reference when data is shared, updated independently, very large, or capable of unbounded growth.
- Retrieval cost: Applications may issue additional queries or use
$lookup, potentially increasing latency and complexity. - Consistency benefit: A shared entity has one authoritative document, reducing duplicate updates.
- Independent identity: Related entities remain in separate collections and are connected using fields such as
- Decision test: Model according to cardinality, ownership, update frequency, data size, and dominant query patterns.
- Hybrid approach: A document may reference the source entity while embedding frequently displayed snapshot fields.
IV. Singular Associations
A. One-to-One Relationships
A one-to-one relationship associates one document with at most one corresponding document, such as one user and one profile.
- Embedded representation: Store the dependent object inside its owner when both are usually read together and share a lifecycle.
{
_id: ObjectId("64f000000000000000000001"),
email: "mina@example.com",
profile: { displayName: "Mina", timezone: "UTC+5:30" }
}- Referenced representation: Store
usersandprofilesseparately when the profile is large, sensitive, rarely accessed, or governed by different permissions. - Relationship direction: The reference should normally be stored on the side from which navigation occurs most often, for example
profile.userId. - Uniqueness constraint: A unique index on the referencing field enforces that no two profiles belong to the same user.
db.profiles.createIndex({ userId: 1 }, { unique: true })- Lifecycle consideration: Embedded profile data is removed automatically with its user document; referenced data requires explicit deletion or archival handling.
- Trade-off: Separation supports independent access and security, while embedding reduces reads and keeps related updates atomic.
V. Parent-Child Associations
A. One-to-Many Relationships
A one-to-many relationship connects one parent to multiple children, and its representation depends mainly on the number and growth of those children.
-
Bounded one-to-few
- Embedding: A customer’s small set of delivery addresses can be stored in an
addressesarray. - Advantage: Reading the customer returns all addresses without a join.
- Condition: The array must remain predictably small and normally be accessed with the parent.
- Embedding: A customer’s small set of delivery addresses can be stored in an
-
Large or unbounded one-to-many
- Referencing: Orders should usually be separate documents containing
customerId, because a customer may create orders indefinitely. - Indexing: An index such as
{ customerId: 1, createdAt: -1 }supports recent-order queries for one customer. - Pagination: Separate child documents permit sorting and limiting without loading the entire relationship.
- Referencing: Orders should usually be separate documents containing
- Avoid unbounded arrays: Continually appending logs, events, or messages enlarges the parent document and can approach the 16 MiB limit.
- Reference placement: Storing the parent identifier in each child generally scales better than maintaining an ever-growing parent array of child identifiers.
- Deletion policy: MongoDB does not automatically cascade deletes; applications must define whether children are deleted, retained, or marked orphaned.
VI. Networked Associations
A. Many-to-Many Relationships
A many-to-many relationship exists when each entity may be associated with multiple entities of another type, such as students and courses.
- Small bounded sets: Each document may store an array of related identifiers when membership is limited and updates are manageable.
- Intermediate collection: A junction-style collection is preferable when the relationship is large or has attributes of its own.
{
_id: ObjectId("64f000000000000000000010"),
studentId: ObjectId("64f000000000000000000011"),
courseId: ObjectId("64f000000000000000000012"),
enrolledAt: ISODate("2025-01-10T00:00:00Z"),
status: "active"
}- Relationship attributes: Fields such as
enrolledAt,status,role, orgradenaturally belong to the association document. - Duplicate prevention: A compound unique index on
{ studentId: 1, courseId: 1 }prevents duplicate enrollment. - Bidirectional queries: Additional indexes may support finding all courses for a student and all students in a course.
- Denormalized identifiers: Storing arrays on both entities speeds reads but requires synchronized updates and can leave inconsistent links.
- Query mechanism:
$lookupcan combine referenced collections, but frequent large joins may indicate that the model does not match the application’s access patterns.
VII. Design Principles
A. Data Modeling Best Practices
Effective MongoDB models balance query performance, write behavior, consistency, and future growth.
- Start with workloads: List high-frequency operations, required filters, sort orders, projected fields, and latency expectations before defining documents.
- Store together what is accessed together: Co-locate data used in the same request when size and update patterns permit it.
- Define aggregate boundaries: Keep values requiring atomic consistency in one document whenever practical.
- Control duplication: Duplicate stable display data, such as an order’s product name, only when faster reads justify synchronization or snapshot semantics.
- Plan for growth: Estimate array cardinality, document size, write rate, and retention period; move unbounded histories to separate collections.
- Use appropriate BSON types: Store dates as BSON dates, numeric values as numeric types, and identifiers consistently as
ObjectIdor another chosen type. - Design indexes with queries: Compound index field order should reflect equality filters, sort operations, and range predicates.
- Limit indexes: Every index consumes storage and adds work to inserts and updates.
- Use schema versioning: A field such as
schemaVersion: 2helps applications migrate or interpret evolving document formats. - Measure decisions: Use
explain()and production-like datasets to confirm index use, documents examined, and execution behavior.
VIII. Applied Modeling
A. Case Studies and Examples
An e-commerce order system demonstrates how embedding and referencing can be combined according to ownership and historical requirements.
- Customer reference: The order stores
customerIdbecause the customer exists independently and may place many orders. - Embedded line items: Each purchased item contains
productId,name,unitPrice, andquantity.productIdlinks to the current catalog product.nameandunitPricepreserve what was displayed and charged when the order was created.
- Embedded shipping address: The address is copied into the order because later customer address changes must not alter historical delivery information.
- Calculated total:
totalmay be stored for rapid retrieval, but the application must calculate it from trusted line-item values during order creation. - Separate payment records: Payment attempts may be stored separately because they have independent security controls, statuses, and potentially repeated attempts.
- Separate shipment events: Tracking events form an unbounded sequence and therefore should not grow indefinitely inside the order document.
- Atomic transition: Updating an order’s status and its embedded summary fields in one operation preserves consistency within the aggregate.
- Resulting model: The case uses references for independently managed entities, embedding for bounded owned data, and snapshot duplication for historical accuracy.
IX. Data Integrity
A. Validation Rules and Constraints
MongoDB supports collection validators that reject or warn about documents violating declared structural and value requirements.
- JSON Schema validation: The
$jsonSchemaoperator can require fields, restrict BSON types, validate arrays, and constrain values. - Concrete rule: An order can require a customer identifier, at least one item, and a recognized status.
db.createCollection("orders", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["customerId", "items", "status"],
properties: {
customerId: { bsonType: "objectId" },
items: {
bsonType: "array",
minItems: 1,
items: {
bsonType: "object",
required: ["productId", "quantity", "unitPrice"]
}
},
status: {
enum: ["pending", "paid", "shipped", "cancelled"]
}
}
}
},
validationLevel: "strict",
validationAction: "error"
})- Validation level:
strictapplies validation to all inserts and relevant updates;moderateprovides a less disruptive path for collections containing older invalid documents. - Validation action:
errorrejects invalid writes, whilewarnrecords violations without rejecting them. - Index constraints: Unique indexes enforce uniqueness for keys such as usernames or relationship pairs; partial unique indexes can apply only to qualifying documents.
- Application validation: Business rules involving authorization, external systems, or complex cross-document conditions still belong in application or service logic.
- Referential integrity: MongoDB does not automatically enforce foreign keys, so applications or transactions must prevent missing references and handle deletions.
- Defense in depth: Database validation protects all write paths, while application validation supplies clearer user-facing errors and domain-specific checks.
Did this save you a night before the exam?
LPU Notes is free, and it stays free. Ads cover part of the server bill. The rest comes out of a student's own pocket: the domain, the storage, and keeping the site up through the weeks everyone needs it at once.
The payment button didn't load. An ad blocker or a filtered network is the usual reason. to try again.
Nothing here is ever locked, and nothing unlocks. Chip in only if it was worth it. What it pays for →