Cómo recuperar el documento original de nuevo después de la agregación

Tengo un caso en el que quiero consultar una colección de documentos que tienen una cantidad de elementos en un campo de matriz “formularios”. El problema a resolver era querer devolver solo los documentos que tienen todos los documentos contenidos en “formularios” con un estado particular de “cerrado”.

Así que aquí hay una muestra de dos documentos diferentes en la colección:

{ "_id" : "Tvq444454j", "name" : "Jim", "forms" : [ { "name" : "Jorney", "status" : "closed" }, { "name" : "Women", "status" : "void" }, { "name" : "Child", "status" : "closed" }, { "name" : "Farm", "status" : "closed" } ] }, { "_id" : "Tvq579754r", "name" : "Tom", "forms" : [ { "name" : "PreOp", "status" : "closed" }, { "name" : "Alert", "status" : "closed" }, { "name" : "City", "status" : "closed" }, { "name" : "Country", "status" : "closed" } ] } 

Y el resultado esperado:

 { "_id" : "Tvq579754r", "name" : "Tom", "forms" : [ { "name" : "PreOp", "status" : "closed" }, { "name" : "Alert", "status" : "closed" }, { "name" : "City", "status" : "closed" }, { "name" : "Country", "status" : "closed" } ] } 

Como no hay un operador de consulta estándar que coincida con todos los elementos de la matriz en esta condición, la solución se encontró mediante la agregación. Esto devolvería el _id de los documentos en la colección que tienen todos sus elementos de “formas” establecidos en el estado de “cerrado”.

 db.forms.aggregate([ {$unwind: "$forms" }, {$group: { _id: "$_id", status: {$addToSet: "$forms.status" }}}, {$unwind: "$status"}, {$sort: { _id: 1, status: -1 }}, {$group: {_id: "$_id", status: {$first: "$status"}}}, {$match:{ status: "closed" }} ]) 

Entonces, como esperaba devolver muchos documentos en los resultados, me gustaría evitar emitir otro hallazgo o una serie de hallazgos solo para obtener los documentos que coinciden con los _id devueltos.

Teniendo esto en cuenta, ¿hay alguna forma de recuperar los documentos originales de la agregación exactamente de la misma forma que están en la colección, mientras sigo haciendo este tipo de filtrado?

Caer bajo la categoría de trucos estúpidos de agregación es una pequeña técnica que a menudo se pasa por alto.

La consulta hace todo su agrupamiento alrededor del documento _id, siendo el identificador único de este documento. Entonces, el punto principal en el que pensar es que el documento completo ya es un identificador único. Entonces, en lugar de esconderse en la tecla _id, use todo el documento.

  {$project: { _id: { _id: "$_id", name: "$name", forms: "$forms" }, forms: "$forms"} }, 

Donde esto se hace, todo lo que enrolla el _id conserva el documento en su forma original. Al final de todas las otras etapas de agregación, emita un proyecto $ final para restaurar el formulario de documento original verdadero:

  {$project: { _id: "$_id._id", name: "$_id.name", forms: "$_id.forms"}} 

Luego tendrá los resultados filtrados que desee. Esta técnica puede ser muy útil cuando se usa con filtrado avanzado, como en el caso de esta consulta, ya que elimina la necesidad de emitir un hallazgo adicional en todos los resultados.

Además, en caso de que sepa que solo está buscando un conjunto de resultados que coincidan con un cierto conjunto de condiciones, use un operador $ match como la primera etapa de la canalización de agregación. Esto no solo es útil para reducir el tamaño del conjunto de trabajo, sino que también es la única etapa en la que puede usar un índice y donde puede boost significativamente el rendimiento de la consulta.

Todo el proceso en conjunto:

 db.forms.aggregate([ {$match: { "forms.status": "closed" } }, {$project: { _id: { _id: "$_id", name: "$name", forms: "$forms" }, forms: "$forms"} }, {$unwind: "$forms"}, {$group: { _id: "$_id", status: {$addToSet: "$forms.status"}}}, {$unwind: "$status"}, {$sort: { _id: 1, status: -1} }, {$group: { _id: "$_id", status: {$first: "$status"} }}, {$match: { status: "closed"}}, {$project: { _id: "$_id._id", name: "$_id.name", forms: "$_id.forms"}} ])