MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Validation de document imbriquée MongoDB pour les sous-documents

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' ?