Skip to content

Latest commit

 

History

History
131 lines (111 loc) · 4.28 KB

File metadata and controls

131 lines (111 loc) · 4.28 KB
title Use Schema Validation
impact MEDIUM
impactDescription Prevents invalid data at database level, catches bugs before production corruption
tags schema, validation, json-schema, data-integrity, fundamentals

Use Schema Validation

Enforce document structure with MongoDB's built-in JSON Schema validation. Catch invalid data before it corrupts your database, not after you've shipped 10,000 malformed documents to production. Schema validation is your last line of defense when application bugs slip through.

Incorrect (no validation):

Without validation, any document shape is accepted: an email field can contain a non-email string, an age field can hold a string instead of a number, and required fields like email can be omitted entirely. These invalid documents are discovered only when downstream consumers crash or return wrong data — often months later.

Correct (schema validation):

// Create collection with validation rules
db.createCollection("users", {
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["email", "name"],
      properties: {
        email: {
          bsonType: "string",
          pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
          description: "must be a valid email address"
        },
        name: {
          bsonType: "string",
          minLength: 1,
          maxLength: 100,
          description: "must be 1-100 characters"
        },
        age: {
          bsonType: "int",
          minimum: 0,
          maximum: 150,
          description: "must be integer 0-150"
        },
        status: {
          enum: ["active", "inactive", "pending"],
          description: "must be one of: active, inactive, pending"
        },
        addresses: {
          bsonType: "array",
          maxItems: 10,  // Prevent unbounded arrays
          items: {
            bsonType: "object",
            required: ["city"],
            properties: {
              street: { bsonType: "string" },
              city: { bsonType: "string" },
              zip: { bsonType: "string", pattern: "^[0-9]{5}$" }
            }
          }
        }
      }
    }
  },
  validationLevel: "strict",
  validationAction: "error"
})

// Invalid inserts now fail immediately with clear error
db.users.insertOne({ email: "not-an-email" })
// Error: Document failed validation:
// "email" does not match pattern, "name" is required

Validation levels and actions:

validationLevel Behavior
strict Validate ALL inserts and updates (default, recommended)
moderate Only validate documents that already match schema
validationAction Behavior
error Reject invalid documents (default, recommended)
warn Allow but log warning (use during migration only)

Add validation to existing collection:

// Start with moderate + warn to discover violations
db.runCommand({
  collMod: "users",
  validator: { $jsonSchema: {...} },
  validationLevel: "moderate",  // Don't break existing invalid docs
  validationAction: "warn"       // Log violations, don't block
})

// Check for violations using the actual validator shape
const info = db.getCollectionInfos({ name: "users" })[0]
const validator = info?.options?.validator
db.users.find({ $nor: [validator] })

// Then switch to strict + error
db.runCommand({
  collMod: "users",
  validationLevel: "strict",
  validationAction: "error"
})

When NOT to use this pattern:

  • Rapid prototyping: Skip validation during early development, add before production.
  • Schema-per-document designs: Some collections intentionally store varied document shapes.
  • Log/event collections: High-write collections where validation overhead matters.

Verify with

// Read current validator and validation settings
const info = db.getCollectionInfos({ name: "users" })[0]
printjson({
  validationLevel: info?.options?.validationLevel,
  validationAction: info?.options?.validationAction,
  validator: info?.options?.validator
})

// Primary compliance check: find documents that do NOT match validator
const validator = info?.options?.validator
db.users.find({ $nor: [validator] })

Reference: Schema Validation