“文档” 菜单
文档首页
/
MongoDB Manual
/ /

使用查询运算符指定验证

在此页面上

  • 限制
  • 上下文
  • 步骤
  • 更多信息
  • 了解详情

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

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

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

  • price

  • VAT

  • totalWithVAT

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

1

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

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

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

2

由于 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
}
}
3

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

db.orders.insertOne( {
total: NumberDecimal("141"),
VAT: NumberDecimal("0.20"),
totalWithVAT: NumberDecimal("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

← JSON 模式验证的技巧