2013-01-25 7 views
11

Ich versuche Daten zuerst nach Datum zu sortieren und dann auf ein anderes Feld zu gruppieren. Es funktioniert nicht für mich.Mongo Aggregation Framework, Sortieren und dann Gruppe funktioniert nicht

Die Frage, die ich versuche zu beantworten, ist: Wählen Sie die letzte distinkte CID?

angesichts dieser Daten:

db.summary.save({"lid" : 5, "date" : 5, "cid" : 2, "circles" : [ 2 ] }) 
db.summary.save({"lid" : 2, "date" : 2, "cid" : 1, "circles" : [ 2 ] }) 
db.summary.save({"lid" : 4, "date" : 0, "cid" : 3, "circles" : [ 2 ] }) 
db.summary.save({"lid" : 3, "date" : 3, "cid" : 2, "circles" : [ 2 ] }) 
db.summary.save({"lid" : 1, "date" : 1, "cid" : 1, "circles" : [ 2 ] }) 

db.summary.aggregate({$match :{circles: 2}, $sort: {date: -1}, $group: {_id: '$cid'}}) 

ich zum ersten Mal auf Kreisen ein Spiel mache, dann eine Art auf Datum, dann eine Gruppe auf cid

Das Ergebnis erhalte ich:

Hier ist meine Analyse:

vor nach Datum passend oder Sortieren, waren die Daten:

"lid" : 5, "date" : 5, "cid" : 2 
"lid" : 2, "date" : 2, "cid" : 1 
"lid" : 4, "date" : 0, "cid" : 3 
"lid" : 3, "date" : 3, "cid" : 2 
"lid" : 1, "date" : 1, "cid" : 1 

Nach nach dem Datum sortiert, würde der Datensatz sein:

"lid" : 5, "date" : 5, "cid" : 2 
"lid" : 3, "date" : 3, "cid" : 2 
"lid" : 2, "date" : 2, "cid" : 1 
"lid" : 1, "date" : 1, "cid" : 1 
"lid" : 4, "date" : 0, "cid" : 3 

So nach Gruppierung, ich das Ergebnis erwarten ist:

{ 
    "result" : [ 
     { 
      "_id" : 2 
     }, 
     { 
      "_id" : 1 
     }, 
     { 
      "_id" : 3 
     } 
    ], 
    "ok" : 1 
} 

Welche Abfrage löst mein Problem?

Warum funktioniert die aktuelle Abfrage nicht für mich?

+0

Die zu aggregierenden Pipeline-Parameter müssen entweder in ein Array eingegeben oder als unabhängige Objekte anstelle eines großen Objekts übergeben werden. Und Ihre Frage bezieht sich auf die Gruppierung auf 'cid', aber der Befehl gruppiert sich auf' $ date'. – JohnnyHK

+0

Das war ein Tippfehler. Es sollte $ group sein: {_id: '$ cid'} – ben39

Antwort

17

Wenn Sie $group nach einem $sort in der Pipeline sind, ist die vorherige Art verloren. Sie müßten so etwas wie dies zu tun, statt, so dass das Datum, das Sie wollen nach der Gruppierung sortieren, indem verfügbar:

db.summary.aggregate(
    {$match: {circles: 2}}, 
    {$group: {_id: '$cid', date: {$max: '$date'}}}, 
    {$sort: {date: -1}}); 

Ergebnis:

[ { _id: 2, date: 5 }, 
    { _id: 1, date: 2 }, 
    { _id: 3, date: 0 } ] 

ein $project bis zum Ende der Pipeline hinzufügen wenn Sie die Ausgabe umformen möchten.

+0

Danke! Das ist genau das, was ich gesucht habe, obwohl ich es bereits herausgefunden habe, als Sie geantwortet haben :) – ben39

+1

Vergessen Sie nicht, dass wenn Sie etwas in der $ Gruppe sortieren wollen, müssen Sie es in die $ sort mit '_id einschließen .Datum'. check http://stackoverflow.com/questions/21265170/mongodb-aggregation-sort-not-working – mwm

+2

"Wenn Sie nach einer $ sortierung in der Pipeline gruppieren, ist die vorherige Sortierung verloren." Dies ist nicht wirklich wahr (möglicherweise veraltet). Es ist nicht nur möglich, aber es ist die bevorzugte Art und Weise, da sort so Indizes verwenden kann: https://docs.mongodb.com/manual/reference/operator/aggregation/sort/#sort-operator-and-performance – slouc