sql >> Base de Datos >  >> NoSQL >> MongoDB

Validación de documentos anidados de MongoDB para subdocumentos

Sí, puedes validar todos los subdocumentos en un documento negando $elemMatch , y puede asegurarse de que el tamaño no sea 1. ¡Aunque no es bonito! Y tampoco es exactamente obvio.

> 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 }

Esto es confuso, ¡pero funciona! Lo que significa es solo aceptar documentos donde ni el tamaño de roles es 1 ni roles tiene un elemento con un name eso no es una string o un created_by eso no es una string .

Esto se basa en el hecho de que, en términos lógicos,

es equivalente a

Tenemos que usar este último ya que MongoDB solo nos da un operador exist.

Prueba

Documentos válidos funcionan:

> 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 })

Si falta un campo de roles , falla:

> 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 campo en roles tiene el tipo incorrecto, falla:

> 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 tiene talla 1 falla:

> db.users.insert({
...   name: 'hello',
...   roles: [
...     {name: 'foo', created_by: '2222'},
...   ]
... })
WriteResult({
    "nInserted" : 0,
    "writeError" : {
        "code" : 121,
        "errmsg" : "Document failed validation"
    }
})

Desafortunadamente, lo único que no puedo entender es cómo asegurar que los roles sean una matriz. roles: {$type: 'array'} parece fallar todo, supongo porque en realidad está comprobando que los elementos son del tipo 'array' ?