使用查询运算符指定验证
您可以使用查询运算符(例如$eq
和)来指定验证$gt
以比较字段。
使用查询运算符进行模式验证的一个常见用例是,当您想要创建在运行时比较多个字段值的动态验证规则时。例如,如果您有一个字段依赖于另一个字段的值并且需要确保这些值彼此正确成比例。
限制
语境
考虑一个跟踪客户订单的应用程序。订单有基本价格和增值税。该orders
集合包含以下字段以跟踪总价:
price
VAT
totalWithVAT
步骤
以下过程使用查询运算符创建模式验证,以确保totalWithVAT
匹配预期的 price
和组合VAT
。
创建一个带有验证的集合。
创建一个
orders
带有模式验证的集合:db.createCollection( "orders", { validator: { $expr: { $eq: [ "$totalWithVAT", { $multiply: [ "$total", { $sum:[ 1, "$VAT" ] } ] } ] } } } )
通过此验证,您只能在
totalWithVAT
字段等于时插入文档total * (1 + VAT)
。确认验证可防止无效文档。
以下操作失败,因为该
totalWithVAT
字段不等于正确的值:db.orders.insertOne( { total: NumberDecimal("141"), VAT: NumberDecimal("0.20"), totalWithVAT: NumberDecimal("169") } )
141 * (1 + 0.20) 等于 169.2,因此该
totalWithVAT
字段的值必须为 169.2。该操作返回此错误:
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 } }
使文件有效并插入。
将文档更新为具有正确的
totalWithVAT
值后,操作成功:db.orders.insertOne( { total: NumberDecimal("141"), VAT: NumberDecimal("0.20"), totalWithVAT: NumberDecimal("169.2") } )
MongoDB返回如下输出,说明插入成功:
{ acknowledged: true, insertedId: ObjectId("6304f4651e52f124b84479ba" }
附加信息
您可以将查询运算符验证与JSON 模式验证相结合。
例如,考虑sales
具有此架构验证的集合:
db.createCollection{ "sales", {
validator: {
"$and": [
// Validation with query operators
{
"$expr": {
"$lt": ["$lineItems.discountedPrice", "$lineItems.price"]
}
},
// Validation with JSON Schema
{
"$jsonSchema": {
"properties": {
"items": { "bsonType": "array" }
}
}
}
]
}
}
前面的验证对 sales
集合中的文档强制执行这些规则:
lineItems.discountedPrice
必须小于lineItems.price
。此规则是使用$lt
运算符指定的。- 该
items
字段必须是一个数组。此规则使用 指定$jsonSchema
。
学到更多
参见
原文:Specify Validation With Query Operators
译者:景圣