sql >> Base de Datos >  >> NoSQL >> MongoDB

Cómo agregar con agrupar por y ordenar correctamente

Aquí hay algunas trampas para entender.

Cuando usa $group los límites se ordenarán en el orden en que fueron descubiertos sin una etapa inicial o final /">$sort operación. Entonces, si sus documentos estaban originalmente en un orden como este:

{ uid: 1, created: ISODate("2014-05-02..."), another_col : "x" },
{ uid: 1, created: ISODate("2014-05-05..."), another_col : "y" },
{ uid: 3, created: ISODate("2014-05-05..."), another_col : "w" },
{ uid: 2, created: ISODate("2014-05-10..."), another_col : "z" },

Entonces simplemente usando $group sin un $sort al final de la canalización le devolvería resultados como este:

{ uid: 1, created: ISODate("2014-05-05..."), another_col : "y" },
{ uid: 3, created: ISODate("2014-05-05..."), another_col : "w" },
{ uid: 2, created: ISODate("2014-05-10..."), another_col : "z" },

Ese es un concepto, pero en realidad parece que lo que espera en los resultados requiere devolver los "últimos otros campos" en un orden ordenado del uid es lo que buscas En ese caso, la forma de obtener el resultado es $sort primero y luego haga uso de $last operador:

db.mycollection.aggregate([

    // Sorts everything first by _id and created
    { "$sort": { "_id": 1, "created": 1 } },

    // Group with the $last results from each boundary
    { "$group": {
        "_id": "$uid",
        "created": { "$last": "$created" },
        "another_col": { "$last": "$created" }
    }}
])

O esencialmente aplique la ordenación a lo que desee.

La diferencia entre $last y $max es que este último elegirá el valor "más alto" para el campo dado dentro de la agrupación _id , independientemente del orden actual ordenado o no ordenado. Por otro lado, $last elegirá el valor que ocurre en la misma "fila" que la "última" agrupación _id valor.

Si realmente estuviera buscando ordenar los valores de una matriz, entonces el enfoque es similar. Manteniendo los miembros de la matriz en el orden "creado", también ordenaría primero:

db.mycollection.aggregate([

    // Sorts everything first by _id and created
    { "$sort": { "_id": 1, "created": 1 } },

    // Group with the $last results from each boundary
    { "$group": {
        "_id": "$uid",
        "row": {
            "$push": {
                "created": "$created",
                "another_col": "$another_col"
            }
        }
    }}
])

Y los documentos con esos campos se agregarán a la matriz en el orden en que ya fueron ordenados.