Specify Validation With Query Operators
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
.