Docs 菜单
Docs 主页
/
MongoDB Manual
/

模式验证

在此页面上

  • 指定验证规则
  • JSON schema
  • 其他查询表达式
  • 行为
  • 限制
  • bypassDocumentValidation
  • 更多信息

版本 3.2 中的新增功能

MongoDB 提供在更新和插入期间执行模式验证的功能。

验证规则基于每个集合。

要在创建新集合时指定验证规则,请使用带有validator选项的 db.createCollection()

要向现有集合添加文档验证,请使用带有validator选项的collMod命令。

MongoDB 还提供了以下相关选项:

  • validationLevel 选项,用于确定 MongoDB 在更新期间将验证规则应用于现有文档的严格程度。

  • validationAction 选项,它决定 MongoDB 是应error并拒绝违反验证规则的文档,还是应warn记录日志中的违规情况但允许无效文档。

版本 3.6 中的新增功能

从版本3.6开始, MongoDB 支持 JSON schema 验证。 要指定 JSON schema 验证,请在validator表达式中使用$jsonSchema操作符。

注意

JSON schema 是执行模式验证的推荐方法。

例如,以下示例使用 JSON schema指定验证规则:

db.createCollection("students", {
validator: {
$jsonSchema: {
bsonType: "object",
required: [ "name", "year", "major", "address" ],
properties: {
name: {
bsonType: "string",
description: "must be a string and is required"
},
year: {
bsonType: "int",
minimum: 2017,
maximum: 3017,
description: "must be an integer in [ 2017, 3017 ] and is required"
},
major: {
enum: [ "Math", "English", "Computer Science", "History", null ],
description: "can only be one of the enum values and is required"
},
gpa: {
bsonType: [ "double" ],
description: "must be a double if the field exists"
},
address: {
bsonType: "object",
required: [ "city" ],
properties: {
street: {
bsonType: "string",
description: "must be a string if the field exists"
},
city: {
bsonType: "string",
description: "must be a string and is required"
}
}
}
}
}
}
})

有关更多信息,请参阅 $jsonSchema

bsonType 定义可以在BSON types页面上找到。

除了使用$jsonSchema查询操作符的 JSON schema 验证之外,MongoDB 还支持使用其他查询操作符进行验证,但以下情况除外:

例如,以下示例使用查询表达式指定验证器规则:

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

提示

另请参阅:

在更新和插入期间进行验证。 向集合添加验证时,现有文档在修改之前不会进行验证检查。

要对现有文档执行验证检查,请使用validate命令或db.collection.validate() shell助手。

validationLevel选项确定 MongoDB 对哪些操作应用验证规则:

  • 如果validationLevelstrict (默认值),MongoDB 将验证规则应用于所有插入和更新。

  • 如果validationLevelmoderate ,MongoDB 将验证规则应用于已满足验证条件的现有文档的插入和更新。 对于moderate级别,不检查对不满足验证条件的现有文档的更新的有效性。

例如,使用以下文档创建 contacts 集合:

db.contacts.insert([
{ "_id": 1, "name": "Anne", "phone": "+1 555 123 456", "city": "London", "status": "Complete" },
{ "_id": 2, "name": "Ivan", "city": "Vancouver" }
])

发出以下命令,将验证器添加到contacts集合中:

db.runCommand( {
collMod: "contacts",
validator: { $jsonSchema: {
bsonType: "object",
required: [ "phone", "name" ],
properties: {
phone: {
bsonType: "string",
description: "must be a string and is required"
},
name: {
bsonType: "string",
description: "must be a string and is required"
}
}
} },
validationLevel: "moderate"
} )

contacts集合现在有一个验证级别为moderate的验证器:

  • 如果您尝试使用_id: 1更新文档,MongoDB 将应用新的验证规则,因为现有文档符合条件。

  • 相反,MongoDB 不会将验证规则应用于对包含_id: 2的文档的更新,因为它不符合验证规则。

从 MongoDB 5.0版本开始,验证器会在不满足验证条件时返回详细的错误信息。 错误输出非常详尽 — 会报告所有错误,而不仅仅是第一个错误。

重要

错误输出供人类使用。它将来可能会更改,不应在脚本中依赖它。

在下一个示例中,这两个更新都与我们上面创建的验证规则不一致,该规则要求 name 是string 。

db.contacts.update(
{ _id: 1 },
{ $set: { name: 10 } }
)
db.contacts.update(
{ _id: 2 },
{ $set: { name: 20 } }
)

以下输出显示带有_id: 1的文档未通过验证,并附有详细解释,如errInfo对象所示。 包含_id: 2的文档更新成功,因为该文档在添加验证时不符合初始条件。

// _id: 1
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation",
"errInfo" : {
"failingDocumentId" : 1,
"details" : {
"operatorName" : "$jsonSchema",
"schemaRulesNotSatisfied" : [
{
"operatorName" : "properties",
"propertiesNotSatisfied" : [
{
"propertyName" : "name",
"details" : [
{
"operatorName" : "bsonType",
"specifiedAs" : {
"bsonType" : "string"
},
"reason" : "type did not match",
"consideredValue" : 10,
"consideredType" : "double"
}
]
}
]
}
]
}
}
}
})
// _id: 2
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

要完全禁用验证,可以将validationLevel设置为off

validationAction选项确定 MongoDB 如何处理违反验证规则的文档:

  • 如果validationActionerror (默认值),MongoDB 将拒绝任何违反验证条件的插入或更新。

  • 如果validationActionwarn ,MongoDB 会记录所有违规,但允许继续进行插入或更新。

例如,使用以下 JSON schema 验证器创建contacts2集合:

db.createCollection( "contacts2", {
validator: { $jsonSchema: {
bsonType: "object",
required: [ "phone" ],
properties: {
phone: {
bsonType: "string",
description: "must be a string and is required"
},
email: {
bsonType : "string",
pattern : "@mongodb\.com$",
description: "must be a string and match the regular expression pattern"
},
status: {
enum: [ "Unknown", "Incomplete" ],
description: "can only be one of the enum values"
}
}
} },
validationAction: "warn"
} )

通过warn validationAction ,MongoDB 会记录任何违规行为,但允许继续进行插入或更新。

例如,以下插入操作违反了验证规则:

db.contacts2.insertOne( { name: "Amanda", status: "Updated" } )

但是,由于validationAction只是warn ,MongoDB 仅记录验证违规消息并允许操作继续。 运行以下命令,查看 MongoDB 日志:

db.adminCommand( { getLog: "global" } )

根据集合使用情况,此命令可能会返回大量数据。 验证错误(日志中的一长行,为便于阅读而在此处重新格式化)包含如下信息:

"{\"t\":{\"$date\":\"2021-01-20T15:59:57.305+00:00\"},
\"s\":\"W\",
\"c\":\"STORAGE\",
\"id\":20294,
\"ctx\":\"conn1\",
\"msg\":\"Document would fail validation\",
\"attr\":{\"namespace\":\"test.contacts2\",
\"document\":{\"_id\":{\"$oid\":\"6008537d42e0d23385568881\"},
\"name\":\"Amanda\",
\"status\":\"Updated\"},
\"errInfo\":{\"failingDocumentId\":{\"$oid\":\"6008537d42e0d23385568881\"},
\"details\":{\"operatorName\":\"$jsonSchema\",
\"schemaRulesNotSatisfied\":[
{\"operatorName\":\"properties\",
\"propertiesNotSatisfied\":[
{\"propertyName\":\"status\",
\"details\":[
{\"operatorName\":\"enum\",
\"specifiedAs\":{\"enum\":[
\"Unknown\",
\"Incomplete\"]},
\"reason\":\"value was not found in enum\",
\"consideredValue\":\"Updated\"}]}]},
{\"operatorName\":\"required\",
\"specifiedAs\":{\"required\":[\"phone\"]},
\"missingProperties\":[\"phone\"]}]}}}}"

不能为 adminlocalconfig 数据库中的集合指定验证器。

无法为 system.* 集合指定验证器。

用户可以使用bypassDocumentValidation选项绕过文档验证。

以下命令可以使用新选项bypassDocumentValidation绕过每个操作的验证:

对于启用了访问控制的部署,要绕过文档验证,经过身份验证的用户必须有 bypassDocumentValidation 动作。内置角色 dbAdminrestore 可执行此动作。

后退

简介