Sì, puoi convalida tutti i documenti secondari in un documento negando $elemMatch
, e puoi assicurarti che la dimensione non sia 1. Non è certo carina però! E neanche esattamente ovvio.
> 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 }
Questo è confuso, ma funziona! Ciò significa accettare solo documenti in cui non sono nemmeno le dimensioni di roles
è 1 né roles
ha un elemento con un name
quella non è una string
o un created_by
quella non è una string
.
Ciò si basa sul fatto che, in termini logici,
Equivale a
Dobbiamo usare quest'ultimo poiché MongoDB ci fornisce solo un operatore esistente.
Prova
I documenti validi funzionano:
> 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 })
Se manca un campo da roles
, fallisce:
> db.users.insert({
... name: 'hello',
... roles: [
... {name: 'foo', created_by: '2222'},
... {created_by: '3333'},
... ]
... })
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
Se un campo in roles
ha il tipo sbagliato, non riesce:
> 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"
}
})
Se roles
ha la taglia 1 non riesce:
> db.users.insert({
... name: 'hello',
... roles: [
... {name: 'foo', created_by: '2222'},
... ]
... })
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
Sfortunatamente, l'unica cosa che non riesco a capire è come garantire che i ruoli siano una matrice. roles: {$type: 'array'}
sembra fallire tutto, presumo perché sta effettivamente verificando che gli elementi siano di tipo 'array'
?