Mongo Json Schema Validator AnyOf не работает

Я создал коллекцию с приведенной ниже проверкой:

{
  $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" : [ ]
})

person Ritienne Gauci    schedule 20.11.2019    source источник
comment
Как вы думаете, что должен делать anyOf?   -  person Relequestual    schedule 20.11.2019
comment
Я ожидаю, что anyof позволит мне вставить документ с полем test1 или test2   -  person Ritienne Gauci    schedule 20.11.2019


Ответы (1)


{test:"123"} не проходит проверку, поскольку не соответствует ни одной из схем в anyOf, для которых в качестве единственного ключа требуется test1 или test2.

anyOf применяет каждую подсхему к вашему экземпляру и утверждает, что она действительна, если хотя бы одна из подсхем проходит проверку.

{test1: "123" } терпит неудачу, потому что корневые схемы additionalProperties: false предотвращают любые ключи в вашем объекте, не определенные в ОДНОМ и том же объекте схемы properties или patternProperties.

Решение состоит в том, чтобы иметь некоторое дублирование.

In THIS example (link is for in browser testing but draft-7 only) , я добавил корневые свойства test1 и test2. Это позволит передавать данные, где у вас есть ключ test1 или test2, но, учитывая, что я не знаю ваших требований, я не могу сказать вам, как изменить схему, чтобы разрешить передачу объекта с ключом 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 вам не поможет. Схема JSON в контексте Mongo может проверять каждый элемент только по отдельности и не имеет возможности проверять набор потенциально вставленных записей.

В приведенной выше примерной схеме я удалил проверку типов, потому что это не имеет отношения к этому вопросу, а bsonType в любом случае отличается от типа схемы JSON.

person Relequestual    schedule 20.11.2019
comment
Спасибо за Ваш ответ. Я попытался удалить полевой тест и вставить документ только с одним полем test1, однако он все еще дает мне неправильную ошибку проверки: ``` - person Ritienne Gauci; 20.11.2019
comment
Определить неправильную ошибку проверки? Можете ли вы обновить свой вопрос, чтобы показать эти дополнительные данные теста, результат, который вы получили, и результат, который вы ожидали, пожалуйста? знак равно - person Relequestual; 20.11.2019
comment
Хорошо, я вижу проблему. Я смогу показать вам решение примерно через час. - person Relequestual; 20.11.2019
comment
Спасибо за ваш вклад :) Жду ваших отзывов :) - person Ritienne Gauci; 20.11.2019
comment
Большое спасибо за Вашу помощь. Очень ценится. - person Ritienne Gauci; 20.11.2019