tri d'agrégation mongodb

J'ai une base de données des étudiants et leurs coordonnées. J'essaie de trouver le code postal qui abrite le plus d'étudiants. Les documents pour les étudiants ressemblent à ceci...

{studentcode: 'smi0001', prénom: 'bob', nom de famille: 'smith', code postal: 2001}

J'ai pensé que je pourrais utiliser le framework d'agrégation pour trouver le code postal avec le plus d'étudiants en faisant quelque chose comme...

db.students.aggregate({$project: { postcode: 1 }, $group: {_id: '$postcode', students: {$sum: 1}}})

Cela fonctionne comme prévu (renvoie les codes postaux comme _id et le nombre d'étudiants dans chaque code postal comme 'étudiants', mais si j'Ajoute $sort au pipeline, il semble essayer de trier par toute la collection d'étudiants au lieu des résultats de l'opération $group.

Ce que j'essaie ressemble...

db.students.aggregate({$project: { postcode: 1 }, $group: {_id: '$postcode', students: {$sum: 1}}, $sort: {_id: -1}})

Mais il renvoie toute la collection et ignore les $project et $group... Ai-je raté quelque chose? Je pensais que je serais juste capable de trier par nombre décroissant d'étudiants et de retourner le premier élément. Merci d'avance pour toute aide.

28
demandé sur Nikhil Wagh 2012-09-17 02:36:26

2 réponses

Tu l'as presque eu...

db.test.aggregate(
  {$group: {_id: '$postcode', students: {$sum: 1}}}, 
  {$sort: {_id: -1}}
);

Donne (j'ai ajouté des données de test correspondant à votre échantillon):

{
  "result" : [
    {
        "_id" : 2003,
        "students" : 3
    },
    {
        "_id" : 2002,
        "students" : 1
    },
    {
        "_id" : 2001,
        "students" : 2
    }
  ],
  "ok" : 1
}

Vous aviez un {} extérieur autour de tout, ce qui causait une certaine confusion. Le groupe et le tri ne fonctionnaient pas comme des opérations distinctes dans le pipeline.

Vous n'aviez pas vraiment besoin du projet pour cette affaire.

Update vous voulez probablement Trier par "étudiants", comme ça, pour obtenir les plus gros codes postaux (par population) en premier:

db.test.aggregate(
  {$group: {_id: '$postcode', students: {$sum: 1}}}, 
  {$sort: {students: -1}}
);
49
répondu Eve Freeman 2012-09-16 23:24:46

Je pense que votre syntaxe est légèrement fausse. Chaque opération d'agrégation dans le pipeline devrait être son propre document.

db.students.aggregate( {$project: ...}, {$group: ...}, {$sort: ...} )

Dans votre cas, il devrait être:

db.students.aggregate(
    {$project: { postcode: 1 }}, 
    {$group: {_id: '$postcode', students: {$sum: 1}}}, 
    {$sort: {students: -1}}
)

Je l'ai testé sur une collection d'échantillons basée sur votre schéma et cela fonctionne pour moi, en triant les codes postaux groupés par nombre d'étudiants, en décroissant.

3
répondu Thomas 2012-09-16 23:39:16