MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Come aggregare con raggruppamento e ordinare correttamente

Ci sono alcuni problemi qui da capire.

Quando utilizzi $group i confini verranno ordinati nell'ordine in cui sono stati scoperti senza una fase iniziale o finale $sort operazione. Quindi, se i tuoi documenti erano originariamente in un ordine come questo:

{ 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" },

Quindi semplicemente usando $group senza $sort alla fine sulla pipeline ti restituirebbe risultati come questo:

{ 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" },

Questo è un concetto, ma in realtà sembra che ciò che ti aspetti nei risultati richieda la restituzione degli "ultimi altri campi" in base a un ordine di uid è quello che stai cercando. In tal caso, il modo per ottenere il risultato è in realtà $sort prima e poi usa $last operatore:

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 essenzialmente applica l'ordinamento a ciò che desideri.

La differenza tra $last e $max è che quest'ultimo sceglierà il valore "più alto" per il campo specificato all'interno del raggruppamento _id , indipendentemente dall'ordinamento corrente in base all'ordine non ordinato. D'altra parte, $last sceglierà il valore che si trova nella stessa "riga" dell'"ultimo" raggruppamento _id valore.

Se stavi effettivamente cercando di ordinare i valori di un array, l'approccio è simile. Mantenendo i membri dell'array nell'ordine "creato", dovresti anche ordinare prima:

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 i documenti con quei campi verranno aggiunti all'array con l'ordine in cui erano già stati ordinati.