MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Como agregar com agrupar por e classificar corretamente


Há algumas capturas aqui para entender.

Quando você usa $group os limites serão classificados na ordem em que foram descobertos sem um estágio inicial ou final $sort Operação. Portanto, se seus documentos estavam originalmente em uma ordem como esta:
{ 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" },

Em seguida, basta usar $group sem um $sort no final do pipeline retornaria 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" },

Esse é um conceito, mas na verdade parece que o que você espera nos resultados exige o retorno dos "últimos outros campos" por uma ordem classificada do uid é o que você está procurando. Nesse caso, a maneira de obter seu resultado é $sort primeiro e depois use o $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" }
    }}
])

Ou essencialmente aplique a classificação ao que você deseja.

A diferença entre $last e $max é que este último escolherá o valor "mais alto" para o campo fornecido dentro do agrupamento _id , independentemente do atual classificado na ordem não classificada. Por outro lado, $last escolherá o valor que ocorre na mesma "linha" que o "último" agrupamento _id valor.

Se você estava realmente procurando classificar os valores de uma matriz, a abordagem é semelhante. Mantendo os membros da matriz na ordem "criada", você também classificaria primeiro:
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"
            }
        }
    }}
])

E os documentos com esses campos serão adicionados ao array na ordem em que já foram ordenados.