Specify Validation With Query Operators
On this page
You can specify validation using query operators such as $eq
and $gt
to compare fields.
A common use case for schema validation with query operators is when you want to create dynamic validation rules that compare multiple field values at runtime. For example, if you have a field that depends on the value of another field and need to ensure that those values are correctly proportional to each other.
Restrictions
-
You can't specify the following query operators in a
validator
object: -
You can't specify schema validation for:
-
Collections in the
admin
,local
, andconfig
databases
-
Context
Consider an application that tracks customer orders. The orders have a base price and a VAT. The orders
collection contains these fields to track total price:
-
price
-
VAT
-
totalWithVAT
Steps
The following procedure creates a schema validation with query operators to ensure that totalWithVAT
matches the expected combination of price
and VAT
.
Create a collection with validation.
Create an orders
collection with schema validation:
db.createCollection( "orders", { validator: { $expr: { $eq: [ "$totalWithVAT", { $multiply: [ "$total", { $sum:[ 1, "$VAT" ] } ] } ] } } } )
With this validation, you can only insert documents if the totalWithVAT
field equals total * (1 + VAT)
.
Confirm that the validation prevents invalid documents.
The following operation fails because the totalWithVAT
field does not equal the correct value:
db.orders.insertOne( { total: NumberDecimal("141"), VAT: NumberDecimal("0.20"), totalWithVAT: NumberDecimal("169") } )
141 * (1 + 0.20) equals 169.2, so the value of the totalWithVAT
field must be 169.2.
The operation returns this error:
MongoServerError: Document failed validation Additional information: { failingDocumentId: ObjectId("62bcc9b073c105dde9231293"), details: { operatorName: '$expr', specifiedAs: { '$expr': { '$eq': [ '$totalWithVAT', { '$multiply': [ '$total', { '$sum': [ 1, '$VAT' ] } ] } ] } }, reason: 'expression did not match', expressionResult: false } }
Make the document valid and insert it.
After updating the document to have the correct totalWithVAT
value, the operation succeeds:
db.orders.insertOne( { total: NumberDecimal("141"), VAT: NumberDecimal("0.20"), totalWithVAT: NumberDecimal("169.2") } )
MongoDB returns the following output, indicating that the insert was successful:
{ acknowledged: true, insertedId: ObjectId("6304f4651e52f124b84479ba") }
Additional Information
You can combine query operator validation with JSON Schema validation.
For example, consider a sales
collection with this schema validation:
db.createCollection{ "sales", { validator: { "$and": [ // Validation with query operators { "$expr": { "$lt": ["$lineItems.discountedPrice", "$lineItems.price"] } }, // Validation with JSON Schema { "$jsonSchema": { "properties": { "items": { "bsonType": "array" } } } } ] } }
The preceding validation enforces these rules for documents in the sales
collection:
-
lineItems.discountedPrice
must be less thanlineItems.price
. This rule is specified using the$lt
operator. -
The
items
field must be an array. This rule is specified using$jsonSchema
.
Learn More
-
To see all query operators available in MongoDB, see Query Selectors.
-
To learn more about the
$expr
operator, which allows the use of aggregation expressions within the query language, see$expr
.