MongoDB JSON Schema变体的模式验证器
项目描述
mongo-schema
扩展的 JSON Schema 验证器,用于 MongoDB的JSON Schema变体.
简介
自MongoDB 3.6以来,MongoDB支持在将文档插入集合时在扩展版本的JSON Schema中附加模式来对集合进行服务器端验证。它几乎与JSON Schema 草案 4 相同,但有一些自定义扩展,以及省略的部分,这些部分当然不会被现有的JSON Schema验证器如Python的 jsonschema 处理。
这本来不是问题,因为我们可以在MongoDB服务器上直接测试我们的模式。然而,任何使用过此功能的人可能都发现,来自服务器的模式验证错误响应可能...不够有帮助[^1]
> db.createCollection("test", {"validator": {"$jsonSchema": {"properties": {"count": {"bsonType": "int"}}}}})
{ "ok" : 1 }
> db.test.insert({"count": "abc"})
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
在这种情况下,我们可以清楚地看到“count”的值不是模式要求的int类型。但对于具有大量模式验证规则的中等大小文档,文档验证错误可能非常难以追踪。
此模块的创建是为了帮助调试使用非平凡模式验证MongoDB文档的应用程序中的验证问题。它扩展了 Draft4Validator 的 jsonschema,以支持MongoDB JSON Schema变体使用的元模式和验证器,特别是支持bsonType
验证器。
[^1]: 实际上,这已经在MongoDB 4.9.0中 修复。
安装
依赖关系
jsonschema
- 以下之一:
pymongo
或pybson
《mongo-schema》包 不 显式包含对《bson》包的依赖。通常,该包作为《pymongo》的一部分被安装,但添加这样一个相对较重的依赖项,并且有一个独立的版本,形式为《pybson》。因此,建议安装其中一个。大多数使用此包的用户已经将其作为依赖之一使用了《pymongo》
$ pip install pymongo mongo-schema
或者
$ pip install pybson mongo-schema
注意:不要将此包与 PyPI 上的《mongoschema》包混淆,后者与之无关。
用法
简单地使用 mongo_schema.validate
,它与 jsonschema.validate
具有相同的接口。以下是一些展示 bsonType
验证的示例
>>> import mongo_schema
>>> mongo_schema.validate(123, {'bsonType': 'int'})
>>> mongo_schema.validate(123, {'bsonType': 'long'})
>>> mongo_schema.validate(2**65, {'bsonType': 'long'})
Traceback (most recent call last):
...
jsonschema.exceptions.ValidationError: 36893488147419103232 is not of type
'long'
>>> mongo_schema.validate(b'\x00\x11\x22', {'bsonType': 'binData'})
>>> from datetime import datetime
>>> mongo_schema.validate(datetime.now(), {'bsonType': 'date'})
请注意,本身架构是针对元架构进行验证的,类似于 MongoDB,明确禁止某些属性,例如 $schema
或 $ref
,以及自定义属性。这将在架构本身上导致验证错误
>>> mongo_schema.validate({}, {'$ref': '#/definitions/myDef'})
Traceback (most recent call last):
...
jsonschema.exceptions.SchemaError: Additional properties are not allowed
('$ref' was unexpected)
...
>>> mongo_schema.validate({}, {'foo': 'bar'})
Traceback (most recent call last):
...
jsonschema.exceptions.SchemaError: Additional properties are not allowed
('foo' was unexpected)
...
您还可以使用 mongo_schema.MongoValidator
创建一个包装特定架构的验证器实例
>>> validator = mongo_schema.MongoValidator({'bsonType': 'objectId'})
>>> from bson import ObjectId
>>> validator.validate(ObjectId())
此包的一个典型用例可能是,在文档插入或更新时,架构验证失败时提供更好的错误输出。例如
document = {'a': 123}
try:
my_db.my_collection.insert_one(document)
except pymongo.errors.WriteError as exc:
if exc.code == 121:
# Get the schema for the collection
opts = my_db.my_collection.options()
schema = opts.get('validator').get('$jsonSchema')
# Raise a jsonschema.ValidationError with more details
if schema is not None:
mongo_schema.validate(document, schema)
raise
这里 exc.code == 121
是 MongoDB 错误代码 DocumentValidationError,尽管据我所知,pymongo 驱动程序并未在任何地方提供此功能。