Um Ihre erste Frage zu beantworten:$group
tut nicht Ordnung bewahren. Es gibt offene Änderungswünsche, die auch die Hintergründe ein wenig hervorheben, aber es sieht nicht so aus, als würde das Produkt geändert, um die Reihenfolge der Eingabedokumente beizubehalten:
- https://jira.mongodb.org/browse/SERVER-24799
- https://jira.mongodb.org/browse/SERVER-4507
- https://jira.mongodb.org/browse/SERVER-21022
Generell kann man zwei Dinge sagen:Man möchte in der Regel erst gruppieren und dann sortieren. Der Grund dafür ist, dass das Sortieren von weniger Elementen (was die Gruppierung im Allgemeinen erzeugt) schneller ist als das Sortieren aller Eingabedokumente.
Zweitens wird MongoDB sicherstellen, dass so effizient und wenig wie möglich sortiert wird. Die Dokumentation Zustände:
Dieser Code erledigt also in Ihrem Fall die Arbeit:
collection.aggregate({
$group: {
_id: '$age',
names: { $push: '$name' }
}
}, {
$sort: {
'_id': 1
}
}, {
$limit: 10
})
BEARBEITEN nach Ihren Kommentaren:
Ich stimme dem zu, was Sie sagen. Und wenn Sie Ihre Logik ein wenig weiterführen, würde ich so weit gehen zu sagen:Wenn $group
schlau genug war, einen Index zu verwenden, sollte es nicht einmal ein $sort
erfordern Stufe am Anfang. Leider ist es nicht (noch nicht wahrscheinlich). So wie die Dinge heute stehen, $group
wird niemals einen Index verwenden und es werden keine Abkürzungen basierend auf den folgenden Phasen verwendet ($limit
in diesem Fall). Siehe auch diesen Link
wo jemand einige grundlegende Tests durchgeführt hat.
Das Aggregations-Framework ist noch ziemlich jung, also wird viel daran gearbeitet, die Aggregations-Pipeline intelligenter und schneller zu machen.
Antworten gibt es hier auf StackOverflow (z. B. hier
). ), wo die Leute vorschlagen, im Voraus ein $sort
zu verwenden Phase, um MongoDB zu "zwingen", irgendwie einen Index zu verwenden. Dies hat jedoch meine Tests (1 Million Aufzeichnungen Ihrer Stichprobenform mit unterschiedlichen Zufallsverteilungen) erheblich verlangsamt.
Wenn es um die Leistung einer Aggregationspipeline geht, ist $match
Phasen am Anfang sind das, was wirklich am meisten hilft. Wenn Sie die Gesamtmenge der Datensätze begrenzen können, die von Anfang an durch die Pipeline gehen müssen, dann ist das Ihre beste Wahl - offensichtlich ...;)