Mongo Json模式验证器AnyOf无法正常工作

时间:2019-11-20 10:18:51

标签: mongodb jsonschema json-schema-validator

我创建了一个具有以下验证的集合:

{
  $jsonSchema: {
    bsonType: 'object',
    additionalProperties: false,
    properties: {
      _id: {
        bsonType: 'objectId'
      },
      test: {
        bsonType: 'string'
      }
    },
    anyOf: [
      {
        bsonType: 'object',
        properties: {
          test1: {
            bsonType: 'string'
          }
        },
        additionalProperties: false
      },
      {
        bsonType: 'object',
        properties: {
          test2: {
            bsonType: 'string'
          }
        },
        additionalProperties: false
      }
    ]
  }
}

“验证操作”设置为“错误”,“验证级别”设置为“中等”。

当我尝试插入包含 test test1 字段的文档时,出现验证错误

Document:
db.dmt9.insert([{test:"123"},{test1:"456"}])

Error:

BulkWriteResult({
        "writeErrors" : [
                {
                        "index" : 0,
                        "code" : 121,
                        "errmsg" : "Document failed validation",
                        "op" : {
                                "_id" : ObjectId("5dd511de1f7b2047ed527044"),
                                "test" : "123"
                        }
                }
        ],
        "writeConcernErrors" : [ ],
        "nInserted" : 0,
        "nUpserted" : 0,
        "nMatched" : 0,
        "nModified" : 0,
        "nRemoved" : 0,
        "upserted" : [ ]
})

由于我要插入包含AnyOf内某个字段之一的文档,所以该文档不能成功插入吗?如果尝试将“验证操作”更改为“警告”,则会插入文档,但是我可以插入其他任何字段。

Test with validation Action - Warning

rs0:PRIMARY> db.dmt9.insert([{test:"123"},{test1:"456"},{test9:123}])
BulkWriteResult({
        "writeErrors" : [ ],
        "writeConcernErrors" : [ ],
        "nInserted" : 3,
        "nUpserted" : 0,
        "nMatched" : 0,
        "nModified" : 0,
        "nRemoved" : 0,
        "upserted" : [ ]
})

更新2: 当我删除现场测试时,我得到了这个验证器:

{
  $jsonSchema: {
    bsonType: 'object',
    additionalProperties: false,
    anyOf: [
      {
        bsonType: 'object',
        properties: {
          test1: {
            bsonType: 'string'
          }
        },
        additionalProperties: false
      },
      {
        bsonType: 'object',
        properties: {
          test2: {
            bsonType: 'string'
          }
        },
        additionalProperties: false
      }
    ],
    properties: {
      _id: {
        bsonType: 'objectId'
      }
    }
  }
}

当我再次尝试插入test1时,仍然收到错误消息“文档验证失败”

rs0:PRIMARY> db.dmt8.insert([{test1:"123"}])
BulkWriteResult({
        "writeErrors" : [
                {
                        "index" : 0,
                        "code" : 121,
                        "errmsg" : "Document failed validation",
                        "op" : {
                                "_id" : ObjectId("5dd51b4766ba25a01fbcf8e6"),
                                "test1" : "123"
                        }
                }
        ],
        "writeConcernErrors" : [ ],
        "nInserted" : 0,
        "nUpserted" : 0,
        "nMatched" : 0,
        "nModified" : 0,
        "nRemoved" : 0,
        "upserted" : [ ]
})

1 个答案:

答案 0 :(得分:1)

{test:"123"}验证失败,因为它不符合anyOf中的任何模式,后者需要test1test2作为唯一密钥。

anyOf将每个子模式应用于您的实例,并在至少一个子模式通过验证时断言有效。

{test1: "123" }失败,因为根模式additionalProperties: false阻止了对象中未在SAME模式对象propertiespatternProperties中定义的任何键。

解决方案是进行一些重复。

THIS示例中(链接仅用于浏览器测试,但仅适用于draft-7),我添加了根属性test1test2。这将允许您通过键为test1test2的数据进行传递,但是由于我不知道您的要求,因此我无法告诉您如何修改架构以允许对象test的密钥可以通过(因为每个anyOf子方案都禁止这样做)。

{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "_id": {},
    "test": {},
    "test1": {},
    "test2": {}
  },
  "anyOf": [
    {
      "type": "object",
      "properties": {
        "test1": {}
      },
      "additionalProperties": false
    },
    {
      "type": "object",
      "properties": {
        "test2": {}
      },
      "additionalProperties": false
    }
  ]
}

如果您要检查要插入的事物之一是test1还是test2,那么恐怕JSON Schema无法帮助您。 Mongo上下文中的JSON Schema只能单独检查每个项目,并且无法验证可能插入的记录的集合。

在上面的示例架构中,我删除了类型检查,因为这与该问题无关,并且bsonType还是与JSON Schema类型不同。