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
validatorobject:You can't specify schema validation for:
Collections in the
admin,local, andconfigdatabases
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:
priceVATtotalWithVAT
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: Decimal128("141"), VAT: Decimal128("0.20"), totalWithVAT: Decimal128("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: Decimal128("141"), VAT: Decimal128("0.20"), totalWithVAT: Decimal128("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.discountedPricemust be less thanlineItems.price. This rule uses the$ltoperator.The
itemsfield must be an array. This rule uses$jsonSchema.
Learn More
To see all query operators available in MongoDB, see Query Predicates.
To learn more about the
$exproperator, which allows the use of aggregation expressions within the query language, see$expr.