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