Sim, você pode valide todos os subdocumentos em um documento negando
$elemMatch
, e você pode garantir que o tamanho não seja 1. Mas com certeza não é bonito! E não exatamente óbvio também. > 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 }
Isso é confuso, mas funciona! O que isso significa é aceitar apenas documentos onde nem o tamanho de
roles
é 1 nem roles
tem um elemento com um name
que não é uma string
ou um created_by
que não é uma string
. Isso se baseia no fato de que, em termos lógicos,
É equivalente a
Temos que usar o último, pois o MongoDB apenas nos fornece um operador existente.
Prova
Documentos válidos funcionam:
> 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 um campo estiver faltando em
roles
, Falha:> 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 um campo em
roles
tem o tipo errado, ele falha:> 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
tem tamanho 1 ele falha:> db.users.insert({
... name: 'hello',
... roles: [
... {name: 'foo', created_by: '2222'},
... ]
... })
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
A única coisa que não consigo descobrir, infelizmente, é como garantir que as funções sejam uma matriz.
roles: {$type: 'array'}
parece falhar em tudo, presumo porque está realmente verificando se os elementos são do tipo 'array'
?