Navigation

Enforce a Document Schema

On this page

Overview

You can control the shape and contents of documents in a collection by defining a document schema. Schemas are regular documents that adhere to the same JSON schema specification as the schema validation built in to the core MongoDB server. You can use schemas to control the type of a field’s value, require specific fields, and validate changes before committing the results of insert and update operations.

This guide walks through creating a document schema for a MongoDB Atlas collection.

Note

This guide requires a linked MongoDB Atlas cluster.

Procedure

1
2

Add Field-Level Schema Definitions

The schema for each collection is a single JSON Schema document. The root-level type of each collection schema is a BSON object schema that represents a document in the collection. You can define additional schemas for document fields within the root schema’s properties field.

Note

The fields available in a JSON schema object depends on the type of value that the schema defines. See the document schema types reference page for details on all of the available schema types.

Example

A group is using Stitch to run a voting app where users aged 13 or older can submit a ranked list of their favorite colors. They store the votes in a MongoDB collection named votes where each document represents a single person’s vote. Each vote must include the person’s name, age, and an array of their favorite colors. Each color has a rank, name, and a hexCode.

The following is a typical document in the votes collection:

{
  "name": "Jane Doe",
  "age": 42,
  "favoriteColors": [
    { "rank": 1, "name": "RebeccaPurple", "hexCode": "#663399" },
    { "rank": 2, "name": "DodgerBlue", "hexCode": "#1E90FF" },
    { "rank": 3, "name": "SeaGreen", "hexCode": "#2E8B57" },
  ]
}

The group can use the following schema to guarantee that the listed constraints are satisfied for each document in the votes collection:

{
  "bsonType": "object",
  "required": ["name", "age", "favoriteColors"],
  "properties": {
    "name": {
      "bsonType": "string"
    },
    "age": {
      "bsonType": "int",
      "minimum": 13,
      "exclusiveMinimum": false
    },
    "favoriteColors": {
      "bsonType": "array",
      "uniqueItems": true,
      "items": {
        "rank": { "bsonType": "int" },
        "name": { "bsonType": "string" },
        "hexCode": {
          "bsonType": "string",
          "pattern": "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$"
        }
      }
    }
  }
}
3

Add Change Validation Expressions

In addition to configuring the content of each field, you can validate changes to documents by defining a validation expression in the validate field of a schema. Validation expressions can use the %%prev and %%prevRoot expansions to access a field or document’s values before the insert or update operation occured.

Example

Consider a collection where the owner of each document is specified in the document’s owner_id field. The business rules for this collection specify that once a document has an owner, the value of owner_id should never change. We can enforce this constraint with the following validation expression that ensures that update operations do not change the owner_id value unless its to assign an owner where there was none previously:

"owner_id": {
  "validate": {
    "%or": [
      { "%%prev": { "%exists": false } },
      { "%%prev": "%%this" }
    ]
  }
}

We could also use the %%prevRoot expansion to create the following equivalent validation expression:

"owner_id": {
  "validate": {
    "%or": [
      { "%%prevRoot.owner_id": { "%exists": false } },
      { "%%prevRoot.owner_id": "%%root.owner_id" }
    ]
  }
}
4

Save the Schema

After you have configured the schema, click Save. After saving, Stitch immediately begins enforcing the schema for all future queries.

Note

Existing documents that do not match the schema are not automatically updated or validated, so future changes to these documents may cause schema validation failures.

1

Export Your Stitch Application

To enforce a document schema with stitch-cli you need to export an application directory for your application.

You can export your application from the Export tab of the Settings page in the Stitch UI, or by running the following command from an authenticated instance of stitch-cli:

stitch-cli export --app-id=<App ID>
2

Add a Rule Configuration File

The rules for a MongoDB collection are configured in the rules subdirectory of the linked cluster’s service directory. The rules configuration file is a JSON file with the same name as the collection namespace. For example, the rules for the collection app.users in the mongodb-atlas cluster are defined in the file /services/mongodb-atlas/rules/app.users.json.

If you have not configured rules for the collection, add a configuration file for it to the rules directory:

touch services/<cluster name>/rules/<db>.<collection>.json

The configuration file should have the following general form:

{
  "roles": [],
  "filters": [],
  "schema": {}
}

Note

This guide focuses on creating a schema for the collection. Check out the other configuration guides to learn how to define roles and permissions and create filters.

3

Add a Schema Document

Add an object schema document to the schema field that. You can use additional schema types to configure specific fields within the properties array. At minimum, the schema should resemble the following:

{
  "bsonType": "object",
  "properties": {
    "<Field Name>": <Schema Document>,
    ...
  }
}

In addition to configuring the content of each field, you can validate changes to documents by defining a validation expression in the validate field of a schema. Validation expressions can use the %%prev and %%prevRoot expansions to access a field or document’s values before the insert or update operation occured.

Example

Consider a collection where the owner of each document is specified in the document’s owner_id field. The business rules for this collection specify that once a document has an owner, the value of owner_id should never change. We can enforce this constraint with the following validation expression that ensures that update operations do not change the owner_id value unless its to assign an owner where there was none previously:

"owner_id": {
  "validate": {
    "%or": [
      { "%%prev": { "%exists": false } },
      { "%%prev": "%%this" }
    ]
  }
}

We could also use the %%prevRoot expansion to create the following equivalent validation expression:

"owner_id": {
  "validate": {
    "%or": [
      { "%%prevRoot.owner_id": { "%exists": false } },
      { "%%prevRoot.owner_id": "%%root.owner_id" }
    ]
  }
}
4

Import Your Application Directory

Once you’ve added the schema to the collection rule configuration file, all that’s left is to import the rule.

Ensure that the rule configuration file is saved then navigate to the root of the exported application directory. Log in to MongoDB Atlas with stitch-cli:

stitch-cli login --username="<MongoDB Cloud Username>" --api-key="<MongoDB Cloud API Key>"

Once you’re logged in, import the directory:

stitch-cli import

Once the import completes, Stitch will immediately begin evaluating the results of all insert and update operations on the collection against the schema to ensure that they conform to your specification.