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 is specified using the$ltoperator.The
itemsfield 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
$exproperator, which allows the use of aggregation expressions within the query language, see$expr.