Skip to main content

MongoDB Schema Validation: A Practical Guide with Examples

This guide teaches you how to enforce clean and consistent data in MongoDB using schema validation, balancing flexibility with structure.
Jul 2, 2025  · 12 min read

MongoDB may be schema-less, but that doesn't mean your data has to be messy.

In this article, you’ll learn everything from the basics of schema validation to advanced use cases using the $jsonSchema operator. You’ll explore how to enforce required fields, restrict data types, apply patterns, and validate nested documents. 

We’ll also cover how validation works during inserts and updates, how to modify existing collections, and when to use different validation levels and actions. 

By the end, you’ll be confident in applying schema validation to your MongoDB collections, keeping your data clean and predictable, without giving up the flexibility MongoDB is known for.

Why Schema Validation Matters in MongoDB

MongoDB’s dynamic document model offers speed and flexibility by allowing documents in the same collection to have different fields or structures. This is a huge advantage during early development or rapid iteration. However, that same flexibility can quickly become a liability, leading to inconsistent, incomplete, or invalid data as your application grows.

That’s where schema validation comes in. It lets you define rules for your documents—such as required fields, specific data types, or nested structures—while still embracing MongoDB’s flexible nature.

In this article, you’ll learn how to use MongoDB’s powerful $jsonSchema operator to apply these rules to your collections. Whether you’re preventing malformed inserts in a new application or retrofitting validation rules onto a legacy database, schema validation helps ensure that your data stays clean, your queries stay predictable, and your application remains stable.

If you're new to working with MongoDB and Python, this MongoDB introductory course is a great way to get hands-on with queries and integrations before diving into schema validation.

Before You Begin

To get the most out of this guide, you’ll need access to a MongoDB Atlas cluster. The free tier is more than enough to follow along.

To make the concepts as clear and applicable as possible, we’ll use a MongoDB Atlas sample datasetspecifically, the sample_mflix database. This dataset includes collections such as movies, comments, users, and theaters, which we’ll reference throughout the article to demonstrate each example. The dataset includes documents with fields like nested objects, arrays, strings, numbers, and optional fields.

Load the sample dataset (if needed)

1. Go to your MongoDB Atlas dashboard.

2. Choose your cluster, click the “…” button, and select Load Sample Dataset.

3. Wait a few minutes until the sample_mflix database becomes available.

Getting Started With Schema Validation

Once your dataset is loaded, connect to your cluster using MongoDB Shell (mongosh) or MongoDB Compass, then switch to the dataset:

use sample_mflix

Exploring the dataset with findOne()

Let’s inspect one of the documents from the movies collection:

db.movies.findOne()

Here’s a simplified version of what you might see:

This query uses findOne() to retrieve a single sample document from the movies collection in the sample_mflix database. The result shows various fields, including title, year, genres, and nested objects like imdb and tomatoes.viewer.

Figure 1. This query uses findOne() to retrieve a single sample document from the movies collection in the sample_mflix database. The result shows various fields, including title, year, genres, and nested objects like imdb and tomatoes.viewer.

This document contains a mix of scalar values, arrays, and nested objects, making it ideal for demonstrating a range of validation techniques. In the next section, we’ll create a new collection based on this structure and define our first validation schema using $jsonSchema.

Supported keywords, extensions, and limitations

MongoDB’s $jsonSchema validation is based on the JSON Schema Draft 4 specification, with some modifications and omissions. While not all features from the original spec are supported, MongoDB includes a focused and practical subset suitable for validating BSON documents.

Here are some of the most commonly used keywords:

  • bsonType: MongoDB-specific type keyword (e.g. "string", "int", "array", "object")
  • required: Specifies which fields must be present
  • minimum/maximum: For numeric range validation
  • pattern: For string format validation using regular expressions
  • enum: Restricts a field to a set of allowed values
  • items, minItems, maxItems: For array validation
  • properties: Defines rules for fields inside an object
  • additionalProperties: Controls whether extra (undefined) fields are allowed

MongoDB intentionally omits some advanced features from the full JSON Schema, such as:

  • Schema references ($ref).
  • Conditional logic (if/then/else).
  • Composition operators (oneOf, allOf, anyOf).

For the complete list of supported options, check the official MongoDB $jsonSchema documentation.

In this article, we’ll focus on the most practical and widely supported keywords, enough to cover common real-world validation needs without overwhelming complexity.

For a broader understanding of how MongoDB fits into the NoSQL landscape, explore this comprehensive tutorial.

Creating a Collection With Basic Validation

Now that we’ve seen the structure of a movies document, let’s create a new collection that enforces some basic rules using $jsonSchema. We’ll start with a few common constraints:

  • title: must be a string and is required
  • year: must be an integer and is required
  • genres: must be an array of strings
  • runtime: must be a positive integer

We’ll call this new collection validated_movies.

Creating the collection

Run the following command to create the collection with validation:

db.createCollection("validated_movies", {
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["title", "year", "runtime"],
      properties: {
        title: {
          bsonType: "string",
          description: "must be a string and is required"
        },
        year: {
          bsonType: "int",
          minimum: 1888,
          description: "must be an integer >= 1888 (year of the first film)"
        },
        runtime: {
          bsonType: "int",
          minimum: 1,
          description: "must be a positive integer and is required"
        },
        genres: {
          bsonType: "array",
          items: {
            bsonType: "string"
          },
          description: "must be an array of strings"
        }
      }
    }
  },
  validationLevel: "strict",
  validationAction: "error"
});

Inserting a valid document

Now, let’s insert a document that follows the schema:

db.validated_movies.insertOne({
  title: "Inception",
  year: 2010,
  runtime: 148,
  genres: ["Action", "Sci-Fi", "Thriller"]
});

✅ This should succeed.

Inserting an invalid document

Try inserting a document missing the title field:

db.validated_movies.insertOne({
  year: 2020,
  runtime: 95,
  genres: ["Drama"]
});

❌ This will fail with a validation error because title is required.The first command inserts a valid movie document into the validated_movies collection, passing all required fields and data types. The second command attempts to insert a document without the required title field, resulting in a validation error.

Figure 2. The first command inserts a valid movie document into the validated_movies collection, passing all required fields and data types. The second command attempts to insert a document without the required title field, resulting in a validation error.

Working with Existing Collections

You don’t need to start from scratch to use schema validation. MongoDB allows you to apply validation rules to existing collections using the collMod command. This is especially useful when you want to add structure to a legacy dataset without affecting existing documents.

In this section, we’ll apply a validator to the movies collection from the sample_mflix database.

Adding a validator with collMod

Let’s enforce a basic rule: Every movie document must have a title field of type string.

db.runCommand({
  collMod: "movies",
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["title"],
      properties: {
        title: {
          bsonType: "string",
          description: "must be a string and is required"
        }
      }
    }
  },
  validationLevel: "moderate",
  validationAction: "warn"
});

Inspecting validation rules on the collection

After modifying the movies collection using the collMod command, you may want to confirm which validation rules are currently active.

To check the current schema validator, run:

db.getCollectionInfos({ name: "movies" })[0].options.validator

This returns the $jsonSchema object that defines the validation rules on the collection. It’s a useful way to verify that your configuration was applied correctly, especially after switching modes like warn to error, or updating the structure of required fields.

Understanding validationLevel and validationAction

  • validationLevel: "moderate": Only validates documents that are being inserted or updated. Existing documents that don’t match the schema will not trigger errors.
  • validationAction: "warn": Instead of rejecting invalid writes, MongoDB logs a warning. This is useful in production when you want to monitor schema violations before enforcing them.

Try inserting a document that violates the schema:

db.movies.insertOne({
  year: 2023
});

You’ll see a warning in the logs, but the write will succeed. You can change the action to "error" later to strictly enforce the rule once you’re confident.

The insertOne() command successfully adds a document that violates the schema rule, because the validation action is set to "warn." MongoDB accepts the write, but the missing title field would have triggered a validation error if "error" were enforced.

Figure 3. The insertOne() command successfully adds a document that violates the schema rule, because the validation action is set to "warn." MongoDB accepts the write, but the missing title field would have triggered a validation error if "error" were enforced.

Validating Nested Documents and Arrays

MongoDB documents often include nested structures, like objects inside objects and arrays of values. Thankfully, $jsonSchema supports validating both. Let’s explore how to apply rules to subdocuments and array contents using fields from the movies collection.

Validating a nested document

In the movies collection, each document includes an embedded imdb object with fields like rating, votes, and id. Let’s enforce a rule that ensures:

  • imdb is an object (if present).
  • imdb.rating is a number between 0 and 10.

Here’s how you would define that:

db.createCollection("validated_nested", {
  validator: {
    $jsonSchema: {
      bsonType: "object",
      properties: {
        imdb: {
          bsonType: "object",
          properties: {
            rating: {
              bsonType: "double",
              minimum: 0,
              maximum: 10,
              description: "Must be a number between 0 and 10"
            }
          }
        }
      }
    }
  }
});

Testing the nested document

✅ Valid insert:

db.validated_nested.insertOne({
  title: "Interstellar",
  imdb: { rating: 8.6 }
});

❌ Invalid insert (rating out of range):

db.validated_nested.insertOne({
  title: "Bad Movie",
  imdb: { rating: 12.5 }
});

This will raise a validation error because the rating is greater than 10.This insert operation fails because the rating field inside the nested imdb object exceeds the maximum allowed value of 10, as defined in the schema. MongoDB throws a validation error due to the violation of the $jsonSchema rule.      Figure 4. This insert operation fails because the rating field inside the nested imdb object exceeds the maximum allowed value of 10, as defined in the schema. MongoDB throws a validation error due to the violation of the $jsonSchema rule.

Validating arrays

You can also enforce array constraints. Let’s say you want to ensure that:

  • genres is an array of strings.
  • The array must have at least one item.

Add this to your schema:

genres: {
  bsonType: "array",
  minItems: 1,
  items: {
    bsonType: "string"
  },
  description: "Must be a non-empty array of strings"
}

Combining Multiple Constraints

In real-world applications, your documents often need to satisfy several validation rules at once—covering required fields, allowed values, types, and nested structures. With $jsonSchema, you can easily combine multiple constraints in a single schema definition.

Let’s build a more complete example using the movies document structure. We’ll enforce the following rules:

  • title: required, must be a string
  • year: required, integer, ≥ 1888
  • rated: optional, but must match a predefined set of values
  • genres: must be a non-empty array of strings
  • imdb.rating: number between 0 and 10
  • tomatoes.viewer.rating: optional, number between 0 and 5

Creating a validated collection

db.createCollection("validated_full", {
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["title", "year"],
      properties: {
        title: {
          bsonType: "string",
          description: "Title is required and must be a string"
        },
        year: {
          bsonType: "int",
          minimum: 1888,
          description: "Year must be an integer >= 1888"
        },
        rated: {
          enum: ["G", "PG", "PG-13", "R", "NC-17"],
          description: "Must be a valid MPAA rating"
        },
        genres: {
          bsonType: "array",
          minItems: 1,
          items: { bsonType: "string" },
          description: "Must be a non-empty array of strings"
        },
        imdb: {
          bsonType: "object",
          properties: {
            rating: {
              bsonType: "double",
              minimum: 0,
              maximum: 10,
              description: "IMDB rating must be between 0 and 10"
            }
          }
        },
        tomatoes: {
          bsonType: "object",
          properties: {
            viewer: {
              bsonType: "object",
              properties: {
                rating: {
                  bsonType: "double",
                  minimum: 0,
                  maximum: 5,
                  description: "Viewer rating must be between 0 and 5"
                }
              }
            }
          }
        }
      }
    }
  }
});

Inserting a valid document: 

db.validated_full.insertOne({
  title: "The Matrix",
  year: 1999,
  rated: "R",
  genres: ["Action", "Sci-Fi"],
  imdb: { rating: 8.7 },
  tomatoes: { viewer: { rating: 4.2 } }
});

Inserting an invalid document:

db.validated_full.insertOne({
  title: "Untitled Project",
  year: 2025,
  rated: "Unrated",
  genres: [],
  imdb: { rating: 15 },
  tomatoes: { viewer: { rating: 6.1 } }
});

This will fail due to:

  • Invalid rated value.
  • Empty genres array.
  • imdb.rating exceeding 10.
  • tomatoes.viewer.rating exceeding 5.

This insert operation fails due to multiple schema violations in the validated_full collection. The rated field contains a value not allowed by the enum, genres is an empty array violating the minItems rule, imdb.rating exceeds the maximum of 10 and has the wrong type, and tomatoes.viewer.rating exceeds the allowed maximum of 5. MongoDB rejects the insert with a detailed validation error.

Figure 5. This insert operation fails due to multiple schema violations in the validated_full collection. The rated field contains a value not allowed by the enum, genres is an empty array violating the minItems rule, imdb.rating exceeds the maximum of 10 and has the wrong type, and tomatoes.viewer.rating exceeds the allowed maximum of 5. MongoDB rejects the insert with a detailed validation error.

Validation Levels and Actions Explained

MongoDB gives you fine-grained control over how and when schema validation is applied. When defining validation rules, two options influence the behavior of your database:

  • validationLevel: When the rule should be enforced
  • validationAction: What happens when a document doesn’t match the rule

validationLevel

This option controls which operations are subject to schema validation.

  • strict: All inserts and updates must conform to the schema. This is the default and safest mode.
  • moderate: Only documents that are being inserted or updated are validated. Existing documents, even if invalid, are left untouched.

When to use:

  • Use strict for new collections where you want to fully enforce the schema from the beginning.
  • Use moderate when applying validation to collections that already contain legacy or unstructured data.

validationAction

This option controls how MongoDB responds when a document violates the validation rules.

  • error: The write operation is rejected, and a validation error is returned.
  • warn: The write is accepted, but a warning is logged internally by the server.

Important: On MongoDB Atlas, warnings from warn are not visible to users—you won’t see them in the UI or standard logs.

When to use:

  • Use warn in development or during gradual rollout to monitor violations without blocking writes.
  • Switch to error when you’re confident that your application is writing valid documents and want to strictly enforce the schema.

Example: Switching from Warn to Error

Let’s say you started with this:

db.runCommand({
  collMod: "validated_full",
  validationAction: "warn",
  validationLevel: "moderate"
});

After observing your application behavior, you can switch to strict enforcement:

db.runCommand({
  collMod: "validated_full",
  validationAction: "error",
  validationLevel: "strict"
});

Two collMod commands are used to modify the validation behavior of the validated_full collection. The first sets the validationAction to "warn" and validationLevel to "moderate," allowing invalid documents to be inserted while logging internal warnings. The second command switches to strict enforcement by setting validationAction to "error" and validationLevel to "strict," ensuring that all inserts and updates must fully comply with the defined schema.

Figure 6. Two collMod commands are used to modify the validation behavior of the validated_full collection. The first sets the validationAction to "warn" and validationLevel to "moderate," allowing invalid documents to be inserted while logging internal warnings. The second command switches to strict enforcement by setting validationAction to "error" and validationLevel to "strict," ensuring that all inserts and updates must fully comply with the defined schema.

Now, any invalid insert or update will be blocked with an error message.

Common Pitfalls and Debugging Tips

When working with schema validation, small mistakes can lead to confusing errors—or worse, documents silently bypassing your rules. Here are some of the most frequent issues and how to avoid them:

Wrong bsonType values

One of the most common mistakes when using $jsonSchema is confusing JSON types with MongoDB’s “bsonType”. While "string" and "array" are straightforward, others like numbers and booleans can be tricky.

For example:

  • Use "int" or "long" for whole numbers.
  • Use "double" for floating point numbers.
  • Use "bool" (not "boolean") for true/false values.
  • Use "object" for subdocuments (not "dict" or "map").
  • Use "array" for lists.

If you’re not sure which type a field is stored as, you can inspect a document using typeof in the Mongo shell or review the data using MongoDB Compass.

Missing required fields in partial updates

When using $set, validation only checks the fields being modified. If you’re expecting a full schema check, make sure you’re doing a full document replacement or using validationLevel: "strict" with application logic enforcing full structure.

Empty arrays passing when they shouldn’t

If you forget to specify minItems, an empty array will pass:

	genres: {
	  bsonType: "array",
	  items: { bsonType: "string" }
	}
	// Accepts empty arrays by default

Use minItems: 1 to ensure at least one value is present.

No error with warn mode

As covered earlier, validationAction: "warn" does not block writes or surface errors in MongoDB Atlas. It only logs internally, so validation may appear to “not work.”

Use "error" mode during development or test environments to catch issues early.

Nested field paths aren’t checked if parent object is missing

If imdb.rating is required, but imdb is missing entirely, MongoDB won’t check the rating.

To enforce validation on nested fields, ensure their parent object is either required or has bsonType: "object".

Querying or updating documents that don’t match the schema

After applying validation to an existing collection, it’s often helpful to identify documents that don’t conform to the new schema. You can do this by using the $jsonSchema operator in a query with $nor or $not.

Example: Find invalid documents in the movies collection

Suppose your schema requires a title of type "string." To find documents that don’t match, you can run:

db.movies.find({
  $nor: [
    { $jsonSchema: {
        bsonType: "object",
        required: ["title"],
        properties: {
          title: { bsonType: "string" }
        }
      }
    }
  ]
});

This will return documents that are missing a title or have a title of the wrong type.

This query uses $nor with $jsonSchema to find documents in the movies collection that do not have a title field of type string. The result shows a document with _id: 683ce0050bd195c35e417534 that only contains the year field, confirming it violates the schema requiring a title. This technique is useful for identifying invalid documents before enforcing stricter validation rules.

Figure 7. This query uses $nor with $jsonSchema to find documents in the movies collection that do not have a title field of type string. The result shows a document with _id: 683ce0050bd195c35e417534 that only contains the year field, confirming it violates the schema requiring a title. This technique is useful for identifying invalid documents before enforcing stricter validation rules.

You can also use this approach to:

  • Audit legacy documents before switching from "warn" to "error."
  • Clean or fix invalid documents programmatically.
  • Generate reports on schema compliance.

Wrap-up: Clean Data Without Sacrificing Flexibility

MongoDB’s schema-less design is one of its greatest strengths, but that doesn’t mean you should leave your data unchecked. With $jsonSchema, you can define powerful validation rules that enforce structure while taking advantage of MongoDB’s flexibility.

Throughout this article, you’ve learned how to:

  • Create collections with validation rules.
  • Apply constraints to new and existing collections.
  • Use nested validation for objects and arrays.
  • Configure validation modes and actions.
  • Debug and refine your schemas with confidence.

Whether building a greenfield app or adding structure to a legacy system, schema validation gives you the tools to protect your data without slowing down development.

Next Steps and Resources

Want to dive deeper? Check out these resources:

Preparing for interviews? These top MongoDB questions will test your understanding of topics like schema validation and more. Looking to validate your skills? This certification guide outlines everything you need to know to get certified in MongoDB.

Remember, start small, test with "warn," and move to "error" once you’re confident—your future self (and your data) will thank you.

FAQs

How does schema validation interact with partial updates using $set?

When you perform an update using operators like $set, MongoDB validates only the modified fields—not the entire document—unless you’re using validationLevel: "strict" and the update replaces the full document. To ensure full validation, you can either use document replacement or enforce the structure in your application layer.

Can I enforce that a field exists only if another field is present?

Not directly. MongoDB’s $jsonSchema doesn’t support conditional validation (if/then/else). However, you can sometimes approximate this with expression-based validation (e.g., using $expr with $cond) or by combining $jsonSchema with a $and wrapper. For more complex logic, handle it in the application.

Are validation rules evaluated before or after schema defaults or transformations?

MongoDB does not apply default values or field transformations at the database level. Validation is applied exactly as the document is received. Any defaulting, coercion, or transformations must be handled by your application logic before writing to the database.

Can I version or evolve schemas over time without breaking old data?

Yes. One common strategy is to use validationLevel: "moderate" while gradually enforcing stricter rules. You can also tag documents with a schemaVersion field and apply conditional logic in your application. MongoDB doesn’t offer built-in schema versioning, so version control must be managed externally.

Does schema validation impact performance for inserts and updates?

Slightly—but typically not enough to matter in most applications. Validation introduces a small overhead per write operation, but it can prevent far more costly issues later by rejecting invalid data early. If you’re validating deeply nested or very large documents, benchmark accordingly.


Samuel Molling's photo
Author
Samuel Molling
LinkedIn

Samuel Molling is a Database Reliability Engineer passionate about automating and scaling secure data infrastructure in the cloud. 

Topics

Learn more about MongoDB with these courses!

Course

Introduction to MongoDB in Python

4 hr
21.8K
Learn to manipulate and analyze flexibly structured data with MongoDB.
See DetailsRight Arrow
Start Course
See MoreRight Arrow
Related

blog

What Is MongoDB? Key Concepts, Use Cases, and Best Practices

This guide explains MongoDB, how it works, why developers love it, and how to start using this flexible NoSQL database.
Karen Zhang's photo

Karen Zhang

15 min

blog

MongoDB Certification: A Complete Guide

Explore everything you need to know about MongoDB certification, including the types, benefits, exam preparation tips, and career opportunities.
Satyam Tripathi's photo

Satyam Tripathi

9 min

blog

MySQL vs MongoDB: Choosing the Right Database for Your Project

Learn the pros, cons, and real-world examples of MySQL vs MongoDB. Compare schema design, performance & scaling to choose the best database for your project.
Mark Pedigo's photo

Mark Pedigo

13 min

Tutorial

How to Create a Database in MongoDB: A Quick Guide

Discover how to create a MongoDB database from the shell or with a script, plus common pitfalls to avoid.
Nic Raboy's photo

Nic Raboy

3 min

Tutorial

MongoDB find(): A Complete Beginner's Guide to Querying Data

This guide explains how to use the MongoDB find() method to query, filter, sort, and paginate data with real-world examples. Perfect for beginners and those transitioning from SQL.
Samuel Molling's photo

Samuel Molling

9 min

Tutorial

Creating Collections in MongoDB: Manual and Automatic Methods

Learn how collections are created in MongoDB, when to define them explicitly, and key configuration options.
Luce Carter's photo

Luce Carter

5 min

See MoreSee More