MongoDB schema validation.

Create with validator

db.createCollection("users", {
    validator: {
        $jsonSchema: {
            bsonType: "object",
            required: ["email", "name"],
            properties: {
                email: {
                    bsonType: "string",
                    pattern: "^[^@]+@[^@]+$",
                },
                name: {
                    bsonType: "string",
                    minLength: 1,
                    maxLength: 100,
                },
                age: {
                    bsonType: "int",
                    minimum: 0,
                    maximum: 150,
                },
                tags: {
                    bsonType: "array",
                    items: { bsonType: "string" },
                    uniqueItems: true,
                },
            },
        },
    },
    validationLevel: "strict",
    validationAction: "error",
})

Modify validator

db.runCommand({
    collMod: "users",
    validator: { $jsonSchema: { ... } },
    validationLevel: "moderate",
})

validationLevel

  • strict (default): all inserts + updates validated.
  • moderate: only existing valid docs validated on update.
  • off: disable.

validationAction

  • error (default): reject invalid.
  • warn: log only.

bsonType vs type

bsonType is BSON-specific (matches int, long, double, decimal, objectId, date, binData).

type is JSON Schema (number, string, etc).

Use bsonType for Mongo.

Enum

status: { enum: ["active", "inactive", "banned"] }

additionalProperties

{
    properties: { name: {...}, email: {...} },
    additionalProperties: false,
}

Reject unknown fields.

Nested

{
    properties: {
        address: {
            bsonType: "object",
            required: ["city"],
            properties: {
                city: { bsonType: "string" },
                country: { bsonType: "string" },
            },
        },
    },
}

Conditional ($cond / oneOf)

{
    oneOf: [
        { required: ["email"] },
        { required: ["phone"] },
    ],
}

Either email OR phone required.

Check existing

db.users.find({ $nor: [ { $jsonSchema: {...} } ] })

Find docs that DON’T match schema.

Drop validator

db.runCommand({ collMod: "users", validator: {} })

App-level validation often better

Mongo validation catches malformed data. But:

  • Pydantic / Zod at app level is more flexible.
  • Combine both: validator as backstop, app does primary.

Common mistakes

  • Adding validator with existing invalid data → strict blocks updates.
  • type vs bsonType confusion.
  • Schema not reflecting actual app behavior.
  • Forgetting required array.
  • additionalProperties: false then app adds new fields → breakage.

Read this next

If you want my validation patterns, they’re at rajpoot.dev .


Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .