A flexible schema still needs guard rails so bad writes from any client can't corrupt data.
MongoDB can validate documents on insert and update with a validator attached to the collection. The usual form is $jsonSchema, a JSON Schema dialect that uses bsonType for MongoDB types: "string", "int", "long", "double", "decimal", "date", "objectId", "array", "object".
Set it at creation with db.createCollection(name, { validator }) or later with the collMod command. Two settings control strictness:
validationLevel:"strict"(default) checks every insert and update;"moderate"skips updates to documents that were already invalid, useful when adding rules to existing data,validationAction:"error"(default) rejects the write;"warn"allows it and logs a warning.
A rejected write fails with "Document failed validation" and, in recent versions, errInfo details explaining which rule failed.
Validation complements, not replaces, checks in your application: it protects the data from every client, including scripts and other services. Keep rules focused on invariants (required keys, types, enums, ranges) and allow evolution, typically by leaving additionalProperties unset so new fields can be added. To evolve a schema, a common approach is a schemaVersion field and code that handles both versions while documents are migrated lazily.
Example
db.createCollection("users", {
validator: { $jsonSchema: {
bsonType: "object",
required: ["email", "createdAt"],
properties: {
email: { bsonType: "string", pattern: "^.+@.+$" },
age: { bsonType: "int", minimum: 0, maximum: 150 },
role: { enum: ["user", "admin"] },
createdAt: { bsonType: "date" }
}
} },
validationAction: "error"
})
db.users.insertOne({ email: "ana@x.io", createdAt: new Date(), role: "user" }) // ok
db.users.insertOne({ email: "nope", createdAt: new Date() })
// MongoServerError: Document failed validationRemember
- $jsonSchema validators check inserts and updates on the server
- Use bsonType for MongoDB types such as date, int, objectId
- validationLevel moderate and validationAction warn help roll rules out gradually
Watch out for
- Declaring age as bsonType "int" while the client sends doubles (JavaScript numbers like 30.5): writes fail.