Oui, vous pouvez valider tous les sous-documents d'un document en annulant $elemMatch
, et vous pouvez vous assurer que la taille n'est pas 1. Ce n'est certainement pas joli ! Et pas tout à fait évident non plus.
> 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 }
C'est déroutant, mais ça marche ! Cela signifie n'accepter que les documents où ni la taille des roles
est 1 ni roles
a un élément avec un name
ce n'est pas une string
ou un created_by
ce n'est pas une string
.
Ceci est basé sur le fait qu'en termes logiques,
Est équivalent à
Nous devons utiliser ce dernier car MongoDB ne nous donne qu'un opérateur existe.
Preuve
Les documents valides fonctionnent :
> 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 })
S'il manque un champ dans roles
, il échoue :
> db.users.insert({
... name: 'hello',
... roles: [
... {name: 'foo', created_by: '2222'},
... {created_by: '3333'},
... ]
... })
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
Si un champ dans roles
a le mauvais type, il échoue :
> 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"
}
})
Si roles
a la taille 1, il échoue :
> db.users.insert({
... name: 'hello',
... roles: [
... {name: 'foo', created_by: '2222'},
... ]
... })
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
La seule chose que je ne comprends malheureusement pas, c'est comment s'assurer que les rôles sont un tableau. roles: {$type: 'array'}
semble tout échouer, je suppose parce qu'il vérifie en fait que les éléments sont de type 'array'
?