Pour répondre à votre première question :$group
n'est pas préserver l'ordre. Il existe des demandes de modifications ouvertes qui mettent également un peu en évidence les arrière-plans, mais il ne semble pas que le produit sera modifié pour préserver l'ordre des documents d'entrée :
- https://jira.mongodb.org/browse/SERVER-24799
- https://jira.mongodb.org/browse/SERVER-4507
- https://jira.mongodb.org/browse/SERVER-21022
Deux choses peuvent être dites en général :vous voulez généralement regrouper d'abord, puis faire le tri. La raison en est que trier moins d'éléments (que le regroupement produit généralement) sera plus rapide que de trier tous les documents d'entrée.
Deuxièmement, MongoDB va s'assurer de trier le plus efficacement et le moins possible. La documentation indique :
Donc, ce code fait le travail dans votre cas :
collection.aggregate({
$group: {
_id: '$age',
names: { $push: '$name' }
}
}, {
$sort: {
'_id': 1
}
}, {
$limit: 10
})
MODIFIER suite à vos commentaires :
Je suis d'accord avec ce que vous dites. Et en poussant votre logique un peu plus loin, j'irais jusqu'à dire :Si $group
était assez intelligent pour utiliser un index alors il ne devrait même pas nécessiter un $sort
étape au départ. Malheureusement, ce n'est pas (pas encore probablement). Dans l'état actuel des choses, $group
n'utilisera jamais d'index et ne prendra pas de raccourcis basés sur les étapes suivantes ($limit
dans ce cas). Voir aussi ce lien
où quelqu'un a effectué des tests de base.
Le cadre d'agrégation est encore assez jeune, donc je suppose qu'il y a beaucoup de travail en cours pour rendre le pipeline d'agrégation plus intelligent et plus rapide.
Il y a des réponses ici sur StackOverflow (par exemple ici
) où les gens suggèrent d'utiliser un $sort
initial stage afin de "forcer" MongoDB à utiliser un index d'une manière ou d'une autre. Cependant, cela a considérablement ralenti mes tests (1 million d'enregistrements de la forme de votre échantillon utilisant différentes distributions aléatoires).
En ce qui concerne les performances d'un pipeline d'agrégation, $match
les étapes au départ sont ce qui aide vraiment le plus. Si vous pouvez limiter le nombre total d'enregistrements qui doivent passer par le pipeline depuis le début, c'est votre meilleur pari - évidemment...;)