Buscar documentos donde un campo se compara con otro en una matriz
Digamos que tengo una colección de documentos que se ven así:
{
"_id" : ObjectId("5afa6df3a24cdb1652632ef5"),
"createdBy" : {
"_id" : "59232a1a41aa651ddff0939f"
},
"owner" : {
"_id" : "5abc4dc0f47f732c96d84aac"
},
"acl" : [
{
"profile" : {
"_id" : "59232a1a41aa651ddff0939f"
}
},
{
"profile" : {
"_id" : "5abc4dc0f47f732c96d84aac"
}
}
]
}
Quiero encontrar todos los documentos dondecreatedBy._id != owner._id
, Y donde elcreatedBy._id
aparece en una de las entradas en elacl
matriz. Eventualmente, querré actualizar todos esos documentos para establecer elowner._id
campo para igualar elcreatedBy._id
campo. Por ahora, solo estoy tratando de descubrir cómo consultar el subconjunto de documentos que quiero actualizar.
Hasta ahora, se me ocurrió esto:
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);
}
)
(He usado la sintaxis de ES5 por si ES6 no está bien)
Pero cuando ejecuto esta consulta, aparece el siguiente error:
Error: error: {"ok": 0, "errmsg": "TypeError: e.profile no está definido: \ n_funcs2 / <@: 2: 36 \ n_funcs2 @: 2: 12 \ n", "código": 139 }
¿Cómo realizo esta consulta / qué está pasando aquí? Hubiera esperado que mi consulta funcionara, basada en docs He leído. Encima,e
debería ser un elemento deacl
array, así que espero que tenga un campoprofile
, pero ese no parece ser el caso.
Nota, estoy usando Mongo 3.2, así que no puedo usar $ expr, que he visto que algunos recursos sugieren es una posibilidad.
Resolució
Resulta que había hecho una suposición incorrecta sobre el esquema de esta colección. La razón por la que me encontré con el error anterior es porque algunos documentos tienen unaacl
matriz con un elemento que no tiene unaprofile
campo. La consulta a continuación verifica este caso. También tiene una sola$where
, porque la forma en que lo había escrito originalmente (con dos) parecía terminar dándome un OR de las condiciones en lugar de un 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);
}
)