Encontre documentos onde um campo se compara a outro em uma matriz
Digamos que eu tenha uma coleção de documentos parecidos com este:
{
"_id" : ObjectId("5afa6df3a24cdb1652632ef5"),
"createdBy" : {
"_id" : "59232a1a41aa651ddff0939f"
},
"owner" : {
"_id" : "5abc4dc0f47f732c96d84aac"
},
"acl" : [
{
"profile" : {
"_id" : "59232a1a41aa651ddff0939f"
}
},
{
"profile" : {
"_id" : "5abc4dc0f47f732c96d84aac"
}
}
]
}
Quero encontrar todos os documentos em quecreatedBy._id != owner._id
E onde ocreatedBy._id
aparece em uma das entradas noacl
array. Eventualmente, desejarei atualizar todos esses documentos para definir oowner._id
campo para igualar ocreatedBy._id
campo. Por enquanto, estou apenas tentando descobrir como consultar o subconjunto de documentos que quero atualizar.
Até agora, eu vim com isso:
db.boards.find({
$where: "this.createdBy._id != this.owner._id",
$where: function() {
return this.acl.some(
function(e) => {
e.profile._id === this.createdBy._id
}, this);
}
)
(Eu usei a sintaxe do ES5, caso o ES6 não esteja ok)
Mas quando executo essa consulta, recebo o seguinte erro:
Erro: erro: {"ok": 0, "errmsg": "TypeError: e.profile está indefinido: \ n_funcs2 / <@: 2: 36 \ n_funcs2 @: 2: 12 \ n", "code": 139}
Como executo essa consulta / o que está acontecendo aqui? Eu esperava que minha consulta funcionasse, com base nodocs Eu li. Acima,e
deve ser um elemento doacl
matriz, então eu espero que ele tenha um campoprofile
, mas esse não parece ser o caso.
Note que estou usando o Mongo 3.2, então não posso usar$ expr, que vi alguns recursos sugerirem ser uma possibilidade.
Resolução
Acontece que eu fiz uma suposição incorreta sobre o esquema dessa coleção. A razão pela qual encontrei o erro acima é porque alguns documentos têm umaacl
matriz com um elemento que não tem umprofile
campo. A consulta abaixo verifica esse caso. Ele também tem um único$where
, porque a maneira como eu o escrevi originalmente (com dois) parecia acabar me dando um OR das condições em vez de um AND.
db.boards.find({
$where: function() {
return this.acl.some(
function(e) => {
e.profile !== undefined && e.profile._id === this.createdBy._id && this.createdBy._id != this.owner._id
}, this);
}
)