对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。

使用查询运算符指定验证

您可以使用查询运算符(例如$eq和$gt来比较字段来指定验证。

使用查询操作符进行模式验证的一个常见使用场景是,您想要创建在运行时比较多个字段值的动态验证规则。例如,如果您有一个字段依赖于另一个字段的值,并且需要确保这些值相互之间的比例正确。

考虑一个追踪客户订单的应用程序。订单有一个基本价格和增值税。orders 集合包含以下字段来追踪总价:

  • price

  • VAT

  • totalWithVAT

以下过程使用查询操作符创建模式验证,以确保 totalWithVAT 与 price 和 VAT 的预期组合匹配。

1

创建具有模式验证的orders集合:

db.createCollection( "orders", { validator: { $expr: { $eq: [ "$totalWithVAT", { $multiply: [ "$total", { $sum:[ 1, "$VAT" ] } ] } ] } } })

通过此验证,您只能在 totalWithVAT 字段等于 total * (1 + VAT) 时插入文档。

2

由于 totalWithVAT 字段不等于正确值,以下操作失败:

db.orders.insertOne( { total: Decimal128("141"), VAT: Decimal128("0.20"), totalWithVAT: Decimal128("169")} )

141 * (1 + 0.20) 等于 169.2,所以 totalWithVAT 字段的值必须为 169.2。

操作返回此错误:

MongoServerError: Document failed validationAdditional information: { failingDocumentId: ObjectId("62bcc9b073c105dde9231293"), details: { operatorName: '$expr', specifiedAs: { '$expr': { '$eq': [ '$totalWithVAT', { '$multiply': [ '$total', { '$sum': [ 1, '$VAT' ] } ] } ] } }, reason: 'expression did not match', expressionResult: false }}
3

将文档更新为具有正确的 totalWithVAT 值后,操作成功完成:

db.orders.insertOne( { total: Decimal128("141"), VAT: Decimal128("0.20"), totalWithVAT: Decimal128("169.2")} )

MongoDB 返回以下输出,表明插入成功:

{ acknowledged: true, insertedId: ObjectId("6304f4651e52f124b84479ba")}

您可以将查询操作符验证与 JSON schema 验证结合起来。

例如,考虑具有以下模式验证的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。

  • 要查看MongoDB中可用的所有查询运算符,请参阅查询谓词。

  • 要详细了解允许在查询语言中使用聚合表达式的 $expr 操作符,请参阅 $expr。