I have created the a collection with the below validation:
{
$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
}
]
}
}
The Validation Action was set to Error and Validation Level to Moderate.
When I try to insert a document containing the field test and test1, I am getting a validation error
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" : [ ]
})
Since I am inserting a document containing one of the fields inside the AnyOf, shouldn't the document be inserted successfully? If I try and change the Validation Action to Warning, the document is inserted however I can insert any other field.
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" : [ ]
})
Update 2: When I remove the field test I get this validator:
{
$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'
}
}
}
}
and when i try to insert test1 again I still get the error message Document failed validation
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" : [ ]
})
{test:"123"}
fails validation because it doesn't conform to any of the schemas inanyOf
, which needtest1
ortest2
as the only key.anyOf
applies each subschema to your instance, and asserts valid if at least one of the subschemas passes validation.{test1: "123" }
fails because the root schemasadditionalProperties: false
prevents any keys in your object not defined in the SAME schema objectproperties
orpatternProperties
.The solution is to have some duplication.
In THIS example (link is for in browser testing but draft-7 only), I've added root properties
test1
andtest2
. This will allow data where you have a key oftest1
ortest2
to pass, but given I don't know your requirements, I can't tell you how to modify the schema to allow an object with a key oftest
to pass (as each of theanyOf
subschemas prevent it).If your intent is to check that one of the things you are inserting has
test1
ortest2
, then I'm afraid JSON Schema cannot help you. JSON Schema in the context of Mongo can only check each item individually, and is not afforded the ability to validate a collection of potentially inserted records.In the above example schema, I've removed type checking because that is not relevant to this question, and bsonType differs from JSON Schema type anyway.