Home | Send Feedback | Share on Bluesky |

MongoDB Schema Validation with Java

Published: 30. July 2025  •  java, mongodb

MongoDB is a NoSQL database known for its flexibility and scalability. One of its key features is that it is schemaless, meaning that documents within a collection do not need to follow a predefined structure. This allows for more agile development and easier handling of evolving data requirements.

However, MongoDB also provides a feature called schema validation, which allows you to enforce rules on the structure and data types of documents within a collection. This ensures data quality and consistency in a database.

What is Schema Validation?

Schema validation in MongoDB allows you to specify rules that document structures must adhere to. These rules are defined using JSON Schema syntax and are associated with a specific collection. When you attempt to insert or update a document, MongoDB checks it against the defined validation rules. If the document violates the rules, MongoDB can either reject the operation or issue a warning, depending on the configured validation action.

Why Use Schema Validation?

Specifying Validation Rules

You can specify validation rules when creating a new collection or adding the rules later. MongoDB uses the $jsonSchema operator to define these rules.

When creating a collection, you pass an option object with a validator field that contains the JSON schema. Here's how to do it in the MongoDB shell (mongosh):

db.createCollection("users", {
   validator: {
      $jsonSchema: {
         ... // JSON schema goes here
      }
   }
})

In Java this looks very similar. The JSON schema can be parsed with Document.parse, wrapped in a ValidationOptions instance and then passed to the createCollection method:

    var jsonSchema = Document.parse(
        """
        {
          $jsonSchema: {
            type: "object",
            required: [ "username", "status", "address" ],
            additionalProperties: false,
            properties: {
               _id: { bsonType: "objectId" },
                  username: { type: "string", minLength: 1, description: "username" },
                  firstName: { type: ["string", "null"] },
                  lastName: { type: "string" },
                  email: { type: "string", pattern: "^.+@.+$"},
                  birthYear: { bsonType: "int", minimum: 1900, maximum: 2025 },
                  hobbies: {
                    type: "array",
                    items: [ { "type": "string", "enum": ["Reading", "Swimming", "Cycling", "Hiking", "Painting"] } ],
               minItems: 1,
               uniqueItems: true
                  },
                  status: { type: "string", enum: [ "active", "inactive" ] },
                  address: {
                    type: "object",
                    required: [ "city" ],
                    additionalProperties: false,
                    properties: {
                      city: { type: "string", minLength: 1 },
                      street: { type: "string" },
                      postalCode: { bsonType: "int" }
                    }
                  }
            }
          }
  }""");

    var validationOptions = new ValidationOptions();
    validationOptions.validator(jsonSchema);

    db.createCollection("users",
        new CreateCollectionOptions().validationOptions(validationOptions));

ValidationJsonSchema.java

In this example, the users collection is created with the following rules:

JSON Schema

MongoDB supports draft 4 of JSON Schema, including core specification and validation specification.

But there are some differences.

Most notable difference is that MongoDB supports the bsonType keyword, which allows you to specify the BSON type of field. This is required because the type keyword in JSON Schema does not cover all types that MongoDB supports. For example objectId used for the _id field is not a valid JSON Schema type, but it is a valid BSON type, therefore you must use bsonType to specify it. bsonType supports all BSON types listed on this page: BSON Data Types.

MongoDB's schema implementation omits these keywords from the JSON Schema specification:

This page in the MongoDB documentation provides a detailed overview of the supported JSON Schema features: MongoDB JSON Schema.

Validation Level and Action

When defining schema validation, you can also specify the validationLevel and validationAction.

validationLevel
Determines which documents the validation rules are applied to.

The default is STRICT.


validationAction
Determines how MongoDB handles documents that violate the validation rules.

The default is ERROR.


You set these options with the ValidationOptions class when creating or modifying a collection.

      MongoDatabase db = mongoClient.getDatabase("validation");
      Document jsonSchema = Document.parse("""
          {
            $jsonSchema: {
              bsonType: "object",
              required: ["name", "phone"],
              properties: {
                 name: {
                   bsonType: "string",
                   description: "must be a string"
                 },
                 phone: {
                   bsonType: "string",
                   description: "must be a string"
                 }
              }
            }
          }
          """);

      ValidationOptions validationOptions = new ValidationOptions().validator(jsonSchema)
          .validationLevel(ValidationLevel.MODERATE)
          .validationAction(ValidationAction.WARN);

      db.createCollection("contacts",
          new CreateCollectionOptions().validationOptions(validationOptions));

ValidationActionDemo.java

With ValidationAction set to WARN, MongoDB will allow inserting and updating invalid documents, but it will log a warning message in the mongod log.

      MongoCollection<Document> contacts = db.getCollection("contacts");
      Document contact = new Document("name", "Alice");
      InsertOneResult result = contacts.insertOne(contact);

ValidationActionDemo.java

mongodb-validation  | {"t":{"$date":"2025-07-30T05:40:24.434+00:00"},"s":"W",  "c":"STORAGE",  "id":20294, "ctx":"conn15",
"msg":"Document would fail validation",
"attr":{"namespace":"validation.contacts","document":{"_id":{"$oid":"6889b048075f9e8258533baf"},"name":"Alice"},
"errInfo":{"failingDocumentId":{"$oid":"6889b048075f9e8258533baf"},
"details":{"operatorName":"$jsonSchema",
"schemaRulesNotSatisfied":[{"operatorName":"required","specifiedAs":{"required":["name","phone"]},
"missingProperties":["phone"]}]}}}}

Note that the calling application does not see the warning; it is only logged in the MongoDB server logs. The WARN action is useful if you want to introduce validation rules to an existing collection. This allows you to see which applications insert or update invalid documents, and you can fix them before switching to ERROR action.


If we set the action to ERROR

      ValidationOptions validationOptions = new ValidationOptions().validator(jsonSchema)
          .validationLevel(ValidationLevel.MODERATE)
          .validationAction(ValidationAction.ERROR);

ValidationActionDemo.java

and then run the same insertOne operation again, the application will throw a MongoWriteException exception:

Exception in thread "main" com.mongodb.MongoWriteException: Write operation error on server localhost:27017. 
Write error: WriteError{code=121, message='Document failed validation', 
details={"failingDocumentId": {"$oid": "6889b2d4ce412af54968e87d"}, 
"details": {"operatorName": "$jsonSchema", 
"schemaRulesNotSatisfied": [{"operatorName": "required", "specifiedAs": {"required": ["name", "phone"]}, 
"missingProperties": ["phone"]}]}}}.

In both examples the application set the validation level to MODERATE, which means that the validation rules are always applied to all inserts. But MongoDB only validates updates to existing documents that were already valid when the validation rules were applied. That means with this setting, we can update existing documents that are invalid, and the update of these documents does not have to pass validation. This setting can be useful when you want to gradually introduce validation rules to an existing collection without needing to migrate all existing documents. This also means that your application must be prepared to handle documents that do not match the validation rules.

Update Validation Rules

You can update the validation rules of an existing collection using the collMod command. This command allows you to modify the validation rules without having to drop and recreate the collection. You can also change the validation level and validation action with this command.

This example first inserts a document into the contacts collection.

    MongoCollection<Document> contacts = db.getCollection("contacts");
    Document contact = new Document("name", "Alice");
    InsertOneResult result = contacts.insertOne(contact);

ValidationRuleUpdateDemo.java

Next the code adds a validation rule to the collection using the collMod command. The rule requires that the name and phone fields are present in each document, and that both fields are strings. The example also sets the validation level and action. Here you also see how to build the JSON schema rule programmatically using the Document class.

    Document jsonSchema = new Document("$jsonSchema",
        new Document("bsonType", "object").append("required", List.of("name", "phone"))
            .append("properties",
                new Document("name",
                    new Document("bsonType", "string").append("description",
                        "must be a string")).append("phone",
                            new Document("bsonType", "string").append("description",
                                "must be a string"))));

    Document collModCommand = new Document("collMod", "contacts")
        .append("validator", jsonSchema).append("validationLevel", "strict") // "strict"
                                                                             // or
                                                                             // "moderate"
        .append("validationAction", "error"); // "error" or "warn"

    Document collModCommandResult = db.runCommand(collModCommand);

ValidationRuleUpdateDemo.java

We can now see what happens when we update the existing document, which is not valid, according to the new validation rules. The update will throw a MongoWriteException exception because the document does not have a phone field and validation level is set to strict.

    Bson updateFilter = Filters.eq("name", "Alice");
    Bson updateOperation = Updates.set("name", "Alice Updated");
    try {
      contacts.updateOne(updateFilter, updateOperation);
    }
    catch (MongoWriteException e) {
      System.out.println("Update failed: " + e);
    }

ValidationRuleUpdateDemo.java

But if we would change the validation level to moderate, the update would succeed, because this document was inserted before the validation rule was applied and therefore MongoDB does not validate the document.

    Document collModCommandModerate = new Document("collMod", "contacts")
        .append("validationLevel", "moderate");
    Document collModCommandModerateResult = db.runCommand(collModCommandModerate);
    System.out.println("Changed validation level to moderate. Result: "
        + collModCommandModerateResult.toJson());

    printCollectionInfo(db, "contacts");

    // update existing document with validation level moderate
    Bson updateFilterModerate = Filters.eq("name", "Alice");
    Bson updateOperationModerate = Updates.set("name", "Alice Updated Moderate");
    contacts.updateOne(updateFilterModerate, updateOperationModerate);

ValidationRuleUpdateDemo.java


To view the validation rules of a collection, you can use the listCollections command. In the options object of the collection information, you will find the validator, validationLevel, and validationAction fields.

    Document collectionInfo = db.listCollections().first();

    System.out.println("Collection: " + collectionName);
    Document options = collectionInfo.get("options", Document.class);
    System.out.println("Validation Rules: " + options.get("validator"));
    System.out.println("Validation Level: " + options.get("validationLevel"));
    System.out.println("Validation Action: " + options.get("validationAction"));

ValidationRuleUpdateDemo.java

Querying and Modifying Valid and Invalid Documents

If you want to introduce validation rules to existing collections, you might need to migrate existing documents to match the new schema. MongoDB makes it easy to query for documents that are valid or invalid.

You can directly pass the JSON schema to the find method to retrieve documents that match the schema. This also works with the aggregate method, where you have to use the $match stage.

    // list all valid documents in the collection
    for (Document document : contacts.find(jsonSchema)) {
      System.out.println("Valid document: " + document.toJson());
    }

    // list all valid documents in the collection with aggregation
    for (Document document : contacts.aggregate(List.of(Aggregates.match(jsonSchema)))) {
      System.out.println("Aggregated valid document: " + document.toJson());
    }

ValidationRuleUpdateDemo.java

To list all invalid documents, you use the $nor operator with the JSON schema. This operation returns documents that do not match the specified schema.

    for (Document document : contacts.find(Filters.nor(jsonSchema))) {
      System.out.println("Invalid document: " + document.toJson());
    }

ValidationRuleUpdateDemo.java

You can use the $nor operator in update operations to modify or delete invalid documents. This example shows how to update all invalid documents to make them valid.

    Bson updateInvalidFilter = Filters.nor(jsonSchema);
    Bson updateInvalidOperation = Updates.set("phone", "000000000");
    contacts.updateMany(updateInvalidFilter, updateInvalidOperation);

ValidationRuleUpdateDemo.java

Here is an example of how to delete all invalid documents.

    contacts.deleteMany(Filters.nor(jsonSchema));

ValidationRuleUpdateDemo.java

Conclusion

This concludes this introduction to MongoDB schema validation and how to use it in Java applications. Schema validation is a valuable tool for ensuring data integrity and consistency. By defining and enforcing rules on your collections, you can improve the reliability and maintainability of your applications.