Да, можетес валидира всички поддокументи в документ чрез отричане на $elemMatch
и можете да се уверите, че размерът не е 1. Със сигурност обаче не е красиво! И също не е съвсем очевидно.
> 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 }
Това е объркващо, но работи! Това означава, че приема само документи, където нито размерът на roles
е 1, нито roles
има елемент с name
това не е string
или created_by
това не е string
.
Това се основава на факта, че от гледна точка на логиката,
Е еквивалентен на
Трябва да използваме последното, тъй като MongoDB ни дава само съществуващ оператор.
Доказателство
Валидни документи работят:
> 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 })
Ако поле липсва от roles
, не успява:
> db.users.insert({
... name: 'hello',
... roles: [
... {name: 'foo', created_by: '2222'},
... {created_by: '3333'},
... ]
... })
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
Ако поле в roles
има грешен тип, не успява:
> 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"
}
})
Ако roles
има размер 1, той е неуспешен:
> db.users.insert({
... name: 'hello',
... roles: [
... {name: 'foo', created_by: '2222'},
... ]
... })
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
Единственото нещо, което не мога да разбера за съжаление, е как да гарантирам, че ролите са масив. roles: {$type: 'array'}
изглежда проваля всичко, предполагам, защото всъщност проверява дали елементите са от тип 'array'
?