Advanced Schema Patterns and Antipatterns / Manage Database Schema Lifecycle

Code Summary: Schema Migration

Here’s the default schema for the reviews documents in our bookstore:

const bookstore_reviews_default = {
    bsonType: "object",
    required: ["_id", "review_id", "user_id", "timestamp", "review", "rating"],
    additionalProperties: false,
    properties: {
        _id: { bsonType: "objectId" },
        review_id: { bsonType: "string" },
        user_id: { bsonType: "string" },
        timestamp: { bsonType: "date" },
        review: { bsonType: "string" },
        rating: {
            bsonType: "int",
            minimum: 0,
            maximum: 5,
        },
        comments: {
            bsonType: "array",
            maxItems: 3,
            items: {
                bsonType: "object",
            },
        },
    },
};

The new version of the schema includes the locale field and looks like this:

const bookstore_reviews_international = {
    bsonType: "object",
    required: [
         "_id",
        "review_id",
        "user_id",
        "timestamp",
        "review",
        "rating",
        "locale",
        "schema_version"
    ],
    additionalProperties: false,
    properties: {        
        _id: { bsonType: "objectId" },
        review_id: { bsonType: "string" },
        user_id: { bsonType: "string" },
        timestamp: { bsonType: "date" },
        review: { bsonType: "string" },
        rating: {
            bsonType: "int",
         minimum: 0,
            maximum: 5,
        },
        comments: {
            bsonType: "array",
            maxItems: 3,
            items: {
                bsonType: "object",
            },
        },
        locale: {
          enum: ["en", "fr"],
        },
        schema_version: {
          enum: ["1.0.0"],
        },
    },
};

To enable schema validation for both schemas simultaneously, we used the $jsonSchema operator and the oneOf keyword:

const schema_migration_validation = { 
    $jsonSchema: { 
       oneOf: [
         bookstore_reviews_default,
         bookstore_reviews_international
       ]
    }
};

To update the schema validation rules for the existing collection we used the collMod command:

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