【译】MongoDB之文档验证

慢慢地开始学会思考。

3.2版本开始

MongoDB提供了在更新和插入阶段验证文档的功能。在每个集合的基础上使用validator选项指定验证规则,它是一个声明了验证规则或表达式的文档。使用除了$near/$nearSphere/$text/$where之外的其他任何操作符来声明表达式。

使用collMod命令和validator选项来向一个已有的集合上增加文档验证。在使用db.createCollection()创建新集合时,也可以使用validator选项来指定文档的验证规则,如下所示:

db.createCollection( "contacts",
   { validator: { $or:
      [
         { phone: { $type: "string" } },
         { email: { $regex: /@mongodb\.com$/ } },
         { status: { $in: [ "Unknown", "Incomplete" ] } }
      ]
   }
}

MongoDB也提供了validationLevel选项,来决定在MongoDB对已存在的稳定进行更新操作时对现有文档进行文档验证的级别;validationAction选项决定了MongoDB应该对那些违反验证规则的文档应该是直接报错并且拒绝还是在日志中警告这个违反但是仍然允许无效的文档。

行为

在更新和插入操作中会触发验证。当我们向一个集合增加验证时,现有的文档在修改之前不会触发验证检查。

现有文档

我们可以使用validationLevel选项来控制MongoDB如何处理现有文档。

默认地,validationLevel的值为strict,MongoDB对所有的插入和更新执行验证规则。将validationLevel设置为moderate可以将验证规则运用与插入和对满足验证准则的现有文档的更新。在moderate级别上,对现有不满足验证准则的文档不会验证其有效性。

示例
考虑contacts集合中的下列文档:

{
   "_id": "125876",
   "name": "Anne",
   "phone": "+1 555 123 456",
   "city": "London",
   "status": "Complete"
},
{
   "_id": "860000",
   "name": "Ivan",
   "city": "Vancouver"
}

使用下面的命令向contacts集合增加一个验证器:

db.runCommand( {
   collMod: "contacts",
   validator: { $or: [ { phone: { $exists: true } }, { email: { $exists: true } } ] },
   validationLevel: "moderate"
} )

现在,contacts集合有一个moderate验证级别的验证器。如果我们尝试更新_id125876的文档,由于已有文档匹配该规则,MongoDB将会运用这个验证规则。相反地,MongoDB不会将验证规则运用到_id860000文档的更新上,因为它不满足验证规则。

如果需要全部禁止验证规则,我们可以将validationLevel设置为off

接受或拒绝无效文档

validationAction选项决定了MongoDB如何处理违反验证规则的文档。

默认地,validationActionerror,MongoDB拒绝任何违反验证准则的插入或更新。当validationAction设置为warn时。MongoDB将所有违反规则的行为惊醒记录,但是会允许插入和更新继续。

示例
下面的示例创建了一个contacts集合,有一个声明插入或者更新文档应该至少匹配下面三个条件之一的验证器:
phone字段是一个字符串
email字段匹配正则表达式
status字段要么是Unknown或者是Incomplete

db.createCollection( "contacts",
   {
      validator: { $or:
         [
            { phone: { $type: "string" } },
            { email: { $regex: /@mongodb\.com$/ } },
            { status: { $in: [ "Unknown", "Incomplete" ] } }
         ]
      },
      validationAction: "warn"
   }
)

在设置了验证器之后,下面的插入操作无法满足验证规则,但是由于validationActionwarn,那么写操作将失败记录到日志中并且会成功插入。

db.contacts.insert( { name: "Amanda", status: "Updated" } )

日志包含集合的完整命名空间以及不满足验证规则的稳定,以及操作的时间:

2015-10-15T11:20:44.260-0400 W STORAGE  [conn3] Document would fail validation collection: example.contacts doc: { _id: ObjectId('561fc44c067a5d85b96274e4'), name: "Amanda", status: "Updated" }

限制条件

我们无法指定admin/localconfig数据库中集合上的验证器。
我们也不能制定system.*集合上制定验证器。

绕过稳定验证

用户可以使用bypassDocumentValidation选项绕过文档验证。下列的命令列表支持bypassDocumentValidation选项,具体如下:
applyOps命令
findAndModify命令和db.collection.findAndModify()方法
mapReduce命令和db.collection.mapReduce()方法
insert命令
update命令
aggregate命令的$outdb.collection.aggregate()方法

对于那些开启了存取控制的部署,如果需要绕过文档验证的话,授权的用户必须有bypassDocumentValidation行为。内置的角色dbAdminrestore提供该行为。

原文链接

打赏

mickey

记录生活,写给几十年后的自己。