Schema Validation
MongoDB is schemaless by default, but that doesn't mean you should give up on data integrity. Schema validation lets you attach a JSON Schema to a collection so the server itself rejects documents that don't match — required fields, types, ranges, and patterns are enforced at the database layer, not just in application code.
Adding a Validator on createCollection
db.createCollection("users", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["email", "name", "age"],
properties: {
email: {
bsonType: "string",
pattern: "^\S+@\S+\.\S+$",
description: "must be a valid email address and is required"
},
name: {
bsonType: "string",
minLength: 1,
description: "must be a non-empty string and is required"
},
age: {
bsonType: "int",
minimum: 0,
maximum: 150,
description: "must be an integer between 0 and 150"
}
}
}
}
})Adding or Changing a Validator on an Existing Collection
db.runCommand({
collMod: "users",
validator: {
$jsonSchema: {
bsonType: "object",
required: ["email", "name"],
properties: {
email: { bsonType: "string" },
name: { bsonType: "string" }
}
}
},
validationLevel: "moderate",
validationAction: "warn"
})$jsonSchema Syntax Building Blocks
Keyword | Purpose |
|---|---|
| Restrict the BSON type: string, int, long, double, bool, date, objectId, array, object, null |
| Array of field names that must be present |
| Per-field schema rules, keyed by field name |
| Value must be one of a fixed list |
| Numeric range bounds |
| String length bounds |
| Regular expression the string must match |
| Schema applied to every element of an array field |
| Set to false to reject unknown fields entirely |
Validating an Enum and a Range
db.createCollection("orders", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["status", "total"],
properties: {
status: {
enum: ["pending", "processing", "shipped", "delivered", "cancelled"],
description: "must be one of the allowed statuses and is required"
},
total: {
bsonType: "double",
minimum: 0,
description: "must be a non-negative number and is required"
},
items: {
bsonType: "array",
minItems: 1,
items: {
bsonType: "object",
required: ["sku", "qty"],
properties: {
sku: { bsonType: "string" },
qty: { bsonType: "int", minimum: 1 }
}
}
}
}
}
}
})validationLevel
Controls which writes get checked against the schema.
Level | Behavior |
|---|---|
| Applies the validator to all inserts and all updates |
| Applies the validator to inserts, and to updates only on documents that already match the schema — lets pre-existing non-conforming documents be edited without being blocked |
| Disables validation entirely (validator stays attached but unused) |
validationAction
Action | Behavior |
|---|---|
| Rejects the write, throws a validation error |
| Allows the write, but logs a warning to the server log |
validationLevel: "moderate" and validationAction: "warn" to see how many documents would fail, then tighten to strict/error once the data is clean.What a Validation Failure Looks Like
db.users.insertOne({ name: "Bob" }) // missing required "email"MongoServerError: Document failed validation
Additional Information:
Details: {
operatorName: '$jsonSchema',
schemaRulesNotSatisfied: [
{ operatorName: 'required', specifiedAs: { required: [ 'email', 'name', 'age' ] },
missingProperties: [ 'email', 'age' ] }
]
}Checking an Existing Validator
db.getCollectionInfos({ name: "users" })[0].options.validatorRemoving Validation
db.runCommand({ collMod: "users", validator: {}, validationLevel: "off" })Bonus: bsonType vs type
$jsonSchema is standard JSON Schema, but MongoDB extends it with bsonType, which understands BSON-specific types (objectId, date, decimal, long) that plain JSON Schema's type keyword doesn't have. Prefer bsonType for anything beyond basic string/number/bool/array/object.
Use
$jsonSchemafor structural, type, and range validation at write time.Use
validationLevel: "moderate"when migrating an existing collection with legacy documents.Use
validationAction: "warn"to dry-run a stricter schema before enforcing it.Combine with application-side validation (Mongoose schemas, Joi/Zod, etc.) — validators are a safety net, not the only layer.