Embedding Data & JSON Schema Validation
Embedding groups related data inside a parent document so one read fetches everything your UI needs. Common patterns: address inside user, line items inside order, config inside tenant, metadata inside file record.
Embedding patterns in practice
Embedding groups related data inside a parent document so one read fetches everything your UI needs. Common patterns: address inside user, line items inside order, config inside tenant, metadata inside file record.
Sub-documents can themselves contain arrays and nested objects. Use consistent field naming across documents in a collection even though MongoDB is schema-less — your application code expects predictable shapes.
Real-life example: A restaurant menu embeds categories and dishes inside one menu document. The waiter reads one card (one query) to describe today's specials — no running to the kitchen for each dish name.
db.menus.insertOne({
restaurantId: ObjectId("..."),
name: "Rishtaara Cafe — Summer Menu",
categories: [
{
name: "Beverages",
items: [
{ name: "Masala Chai", price: 49, tags: ["hot", "vegetarian"] },
{ name: "Cold Coffee", price: 99, tags: ["cold"] }
]
},
{
name: "Snacks",
items: [
{ name: "Samosa", price: 30, tags: ["fried", "vegetarian"] }
]
}
],
updatedAt: new Date()
})db.menus.updateOne(
{ "categories.items.name": "Masala Chai" },
{ $set: { "categories.$[cat].items.$[item].price": 59 } },
{ arrayFilters: [{ "cat.name": "Beverages" }, { "item.name": "Masala Chai" }] }
)JSON Schema validation with $jsonSchema
MongoDB lets you attach a JSON Schema validator to a collection. Inserts and updates that violate the schema are rejected. This gives you SQL-like guardrails while keeping document flexibility.
Use validationLevel: "moderate" to validate updates and new inserts but not existing invalid documents. Use validationAction: "error" (default) to reject bad writes.
Real-life example: JSON Schema validation is a bouncer at a club door — checks ID format and dress code before anyone enters, but existing members inside are not kicked out retroactively (with moderate level).
db.createCollection("students", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name", "email", "grade"],
properties: {
name: {
bsonType: "string",
description: "Full name — required string"
},
email: {
bsonType: "string",
pattern: "^[\\w.-]+@[\\w.-]+\\.\\w{2,}$",
description: "Valid email address"
},
grade: {
bsonType: "int",
minimum: 1,
maximum: 12,
description: "Grade level 1–12"
},
subjects: {
bsonType: "array",
items: { bsonType: "string" },
maxItems: 20
},
gpa: {
bsonType: ["double", "decimal", "null"],
minimum: 0,
maximum: 10
}
},
additionalProperties: true
}
},
validationLevel: "strict",
validationAction: "error"
})db.runCommand({
collMod: "students",
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name", "grade"],
properties: {
name: { bsonType: "string" },
grade: { bsonType: "int", minimum: 1, maximum: 12 }
}
}
},
validationLevel: "moderate"
})Common bsonType values and rules
- bsonType: "object" — embedded document; "array" — list with optional items schema.
- bsonType: "string", "int", "long", "double", "decimal", "bool", "date", "objectId", "binData".
- required — array of field names that must exist on every valid document.
- minimum / maximum — numeric bounds; minLength / maxLength — string and array size limits.
- enum — restrict to allowed values: { enum: ["active", "inactive", "pending"] }.
- pattern — regex for string format validation (emails, phone numbers, slugs).
db.createCollection("orders", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["userId", "status", "items", "total"],
properties: {
status: { enum: ["pending", "confirmed", "shipped", "cancelled"] },
total: { bsonType: ["int", "long", "double"], minimum: 0 },
items: {
bsonType: "array",
minItems: 1,
items: {
bsonType: "object",
required: ["name", "qty", "price"],
properties: {
name: { bsonType: "string" },
qty: { bsonType: "int", minimum: 1 },
price: { bsonType: "double", minimum: 0 }
}
}
}
}
}
}
})