Tak, możesz zweryfikuj wszystkie dokumenty podrzędne w dokumencie, negując $elemMatch
, i możesz upewnić się, że rozmiar nie wynosi 1. To na pewno nie jest ładne! I też niezupełnie oczywiste.
> 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 }
To mylące, ale działa! Oznacza to, że akceptuj tylko dokumenty, w których nie ma rozmiaru roles
to 1 ani roles
zawiera element z name
to nie jest string
lub created_by
to nie jest string
.
Opiera się to na fakcie, że w kategoriach logicznych
Jest odpowiednikiem
Musimy użyć tego ostatniego, ponieważ MongoDB daje nam tylko operator istnieje.
Dowód
Prawidłowe dokumenty działają:
> 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 })
Jeśli brakuje pola w roles
, nie powiedzie się:
> db.users.insert({
... name: 'hello',
... roles: [
... {name: 'foo', created_by: '2222'},
... {created_by: '3333'},
... ]
... })
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
Jeśli pole w roles
ma zły typ, nie powiedzie się:
> 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"
}
})
Jeśli roles
ma rozmiar 1, nie powiedzie się:
> db.users.insert({
... name: 'hello',
... roles: [
... {name: 'foo', created_by: '2222'},
... ]
... })
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
Jedyną rzeczą, której niestety nie mogę zrozumieć, jest zapewnienie, że role są tablicą. roles: {$type: 'array'}
wydaje się, że wszystko zawodzi, przypuszczam, ponieważ faktycznie sprawdza, czy elementy są typu 'array'
?