MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Wie man mit Gruppieren nach aggregiert und richtig sortiert

Hier gibt es ein paar Haken zu verstehen.

Wenn Sie $group verwenden die Grenzen werden in der Reihenfolge sortiert, in der sie entdeckt wurden, ohne Anfangs- oder Endstufe $sort Betrieb. Wenn Ihre Dokumente also ursprünglich in folgender Reihenfolge vorlagen:

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

Verwenden Sie dann einfach $group ohne $sort am Ende der Pipeline würde Ihnen folgende Ergebnisse zurückgeben:

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

Das ist ein Konzept, aber es scheint tatsächlich so, als ob das, was Sie in Ergebnissen erwarten, die Rückgabe der "letzten anderen Felder" in einer sortierten Reihenfolge der uid erfordert ist das, wonach Sie suchen. In diesem Fall erhalten Sie Ihr Ergebnis über $sort zuerst und verwenden Sie dann den $last Betreiber:

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" }
    }}
])

Oder wenden Sie die Sortierung im Wesentlichen auf das an, was Sie möchten.

Der Unterschied zwischen $last und $max ist, dass letzterer den "höchsten" Wert für das angegebene Feld innerhalb der Gruppierung _id wählt , unabhängig von der aktuellen Reihenfolge sortiert nach unsortiert. Andererseits $last wählt den Wert, der in derselben "Zeile" wie die "letzte" Gruppierung _id vorkommt Wert.

Wenn Sie tatsächlich die Werte eines Arrays sortieren möchten, ist der Ansatz ähnlich. Wenn Sie die Array-Mitglieder in der "erstellten" Reihenfolge halten, würden Sie auch zuerst sortieren:

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"
            }
        }
    }}
])

Und die Dokumente mit diesen Feldern werden dem Array in der Reihenfolge hinzugefügt, in der sie bereits sortiert waren.