Tengo el siguiente escenario en MongoDB:
Cada registro tiene su propio _id y un parentId. Si parentId== "" entonces es un registro principal verdadero. Si parentId tiene un valor, entonces ese registro es en realidad un elemento secundario que apunta al registro principal. A continuación se muestra un padre y su hijo vinculado.
{"_id": ObjectId('586c9d275d2f62e1634978db'), parentId="", count=1, <other fields>} {"_id": ObjectId('586c9d275d2f62e163497811'), parentId=ObjectId('586c9d275d2f62e1634978db'), count=3, <other fields>}
Quería una consulta en la que encontrara todos los registros principales ordenados por el campo de conteo donde todos los registros principales y secundarios se agrupan. Por ejemplo, más fácil explicado a través del diagrama:
ID6 tiene el valor de conteo más alto que está asociado al padre ID5. El siguiente recuento más alto es ID2, que está asociado al padre ID1, finalmente ID4 es un padre y también debe devolverse, por lo que los resultados deberían ser:
ID5, ID1, ID4
HoefMeistert me ayudó a formular la siguiente consulta:
Clasificación de MongoDB en niños
db.collection.aggregate( [ { $project: { group_id : { $cond : { if: { $ne: [ "$parentId", "" ] }, then: "$parentId", else: "$_id" }}, count :1, field1:1, field2:1 } }, { $group: { _id : "$group_id", highest : { $max: "$count" } }, "field1":{"$first":"$field1"}, "field2":{"$first":"$field2"}, }, { $sort: { highest : -1 } } ] );
El problema con esta consulta es que no devuelve el campo 1 y el campo 2 asociados a los padres, es decir, ID1 e ID5 en el diagrama. ¿Hay alguna manera de proyectar los campos correctos asociados a los padres en la fase de grupos? De lo contrario, si la fase de grupos arroja algo como:
{'_id': ObjectId('586c9d275d2f62e1634978db'), 'highest': 2} {'_id': ObjectId('586c9d0d5d2f62e1634978d5'), 'highest': 1} {'_id': ObjectId('586c9d365d2f62e1634978e3'), 'highest': 0}
¿Cómo puedo volver a emparejar después del grupo para recuperar todos los registros de todas las identificaciones anteriores? Es decir, 586c9d275d2f62e1634978db, 586c9d0d5d2f62e1634978d5, 586c9d365d2f62e1634978e3 ??
Su consulta tiene un error, el field1
1 y field2
deben estar dentro del dictado de $group
:
db.collection.aggregate([ { $project: { group_id: { $cond: { if: { $ne: [ "$parentId", "" ] }, then: "$parentId", else: "$_id" }}, count: 1, field1: 1, field2: 1 } }, { $group: { _id: "$group_id", highest: { $max: "$count"}, field1: { "$first": "$field1"}, field2: { "$first":" $field2"}, }, }, { $sort: { highest : -1 } } ]);
Resultado basado en su diagrama:
{ "_id" : "5", "highest" : 5, "field1" : ..., "field2" : ... } { "_id" : "1", "highest" : 3, "field1" : ..., "field2" : ... } { "_id" : "4", "highest" : 1, "field1" : ..., "field2" : ... }
Editar:
db.colección.agregado([ { $proyecto: { group_id: { $cond: { if: { $ne: [ "$parentId", "" ] }, luego: "$parentId", else: "$_id" }}, contar: 1, field1: { $cond: { if: { $ne: [ "$parentId", "" ] }, luego: nulo, else: "$field1" }}, field2: { $cond: { if: { $ne: [ "$parentId", "" ] }, luego: nulo, else: "$field2" }}, } }, { $grupo: { _id: "$id_grupo", más alto: { $max: "$count"}, campo1: { "$max" : "$campo1"}, campo2: { "$max" :"$campo2"}, }, }, { $clasificar: { más alto: -1 } } ]);
Con esta edición, en la fase de grupos solo los padres tendrán valores para field1
, field2
, otros documentos tendrán valores null
. Entonces podemos hacer un $max
de ellos, para obtener el único valor, el valor principal.
El resultado será el mismo que el anterior, y field1
, field2
tendrán valores de documentos principales