MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Convalida dei documenti annidati MongoDB per documenti secondari

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