Ja, du kan validera alla underdokument i ett dokument genom att negera $elemMatch
, och du kan se till att storleken inte är 1. Det är säkert inte vackert! Och inte direkt självklart heller.
> db.createCollection('users', {
... validator: {
... name: {$type: 'string'},
... roles: {$exists: 'true'},
... $nor: [
... {roles: {$size: 1}},
... {roles: {$elemMatch: {
... $or: [
... {name: {$not: {$type: 'string'}}},
... {created_by: {$not: {$type: 'string'}}},
... ]
... }}}
... ],
... }
... })
{ "ok" : 1 }
Detta är förvirrande, men det fungerar! Vad det betyder är att bara acceptera dokument där varken storleken på roles
är 1 eller roles
har ett element med ett name
det är inte en string
eller en created_by
det är inte en string
.
Detta är baserat på det faktum att i logiska termer,
Motsvarar
Vi måste använda den senare eftersom MongoDB bara ger oss en existerande operatör.
Bevis
Giltiga dokument fungerar:
> db.users.insert({
... name: 'hello',
... roles: [],
... })
WriteResult({ "nInserted" : 1 })
> db.users.insert({
... name: 'hello',
... roles: [
... {name: 'foo', created_by: '2222'},
... {name: 'bar', created_by: '3333'},
... ]
... })
WriteResult({ "nInserted" : 1 })
Om ett fält saknas i roles
, det misslyckas:
> db.users.insert({
... name: 'hello',
... roles: [
... {name: 'foo', created_by: '2222'},
... {created_by: '3333'},
... ]
... })
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
Om ett fält i roles
har fel typ, det misslyckas:
> db.users.insert({
... name: 'hello',
... roles: [
... {name: 'foo', created_by: '2222'},
... {name: 'bar', created_by: 3333},
... ]
... })
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
Om roles
har storlek 1 den misslyckas:
> db.users.insert({
... name: 'hello',
... roles: [
... {name: 'foo', created_by: '2222'},
... ]
... })
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
Det enda jag tyvärr inte kan lista ut är hur man säkerställer att roller är en array. roles: {$type: 'array'}
verkar misslyckas med allt, antar jag eftersom det faktiskt kontrollerar att elementen är av typen 'array'
?