2012-09-16 13 views
27

Tengo una base de datos de estudiantes y sus datos de contacto. Estoy tratando de averiguar el código postal que alberga a la mayoría de los estudiantes. Los documentos para los estudiantes ven algo como esto ...agregación mongod sort

{studentcode: 'smi0001', nombre: 'Bob', el apellido: 'Smith', Código postal: 2001 }

I pensé que podía utilizar el marco de la agregación para averiguar el código postal con el mayor número de estudiantes por hacer algo así ...

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

esto funciona como se espera (devuelve los códigos postales como _id y el número de estudiantes en cada código postal como 'estudiantes', pero si agrego $sort a la tubería, parece que intente ordenar por toda la colección de estudiantes en lugar de los resultados de la operación $group.

lo que estoy tratando mirada como ...

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

pero devuelve toda la colección y descarta el algo $project y $group ... me falta? Pensé que podría ordenar por el número descendente de estudiantes y devolver el primer artículo. Gracias de antemano por cualquier ayuda.

Respuesta

47

Casi lo tenía ...

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

da (he añadido algunos datos de prueba que coincidan con la muestra):

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

Usted tenía un exterior {} alrededor de todo lo que estaba causando cierta confusión . El grupo y el género no funcionaban como operaciones separadas en la tubería.

Realmente no necesita el proyecto para este caso.

actualización Es posible que desee para ordenar por "estudiantes", como tal, para obtener los códigos postales más grandes (por la población) en primer lugar:

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

Muchas gracias por el consejo. No puedo creer que sea solo un problema de soporte extraviado. Este es el tipo de problemas que solía tener para aprender SQL hace 15 años, mudarme a mongodb ha significado dejar atrás tanto conocimiento previo, pero creo que valdrá la pena. Cheers, –

+0

Funciona para su caso de uso, pero este enfoque no siempre garantiza los resultados que espera ver. Por ejemplo, los resultados serán incorrectos cuando deba agrupar por 'campo1' pero guárdelos por' campo2'. – astronaut

+0

Tenía códigos postales POST1, POST2, POST3, cada código postal tiene diferente número de estudiantes. Cuál debería ser mi consulta de clasificación para obtener la suma de cada POST. db.test.aggregate ( {$ group: {_id: {'postcodes': '$ postcodes'}, estudiantes: {$ sum: 1}}}, ¿Cuál debería ser la consulta de ordenación aquí. ); –

3

creo que su sintaxis es un poco mal. Cada operación de agregación en la canalización debe ser su propio documento.

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

En su caso, debe ser:

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

que he probado en una colección de muestras basado en el esquema y funciona para mí, la clasificación de los códigos postales agrupados por número de alumnos descendiendo

+0

¿'$ project' hace algo por usted en este caso? –

+0

@WesFreeman Tienes razón, el proyecto $ podría omitirse. Supongo que si tuviera documentos realmente grandes, reducirlos a solo la información necesaria para un procesamiento posterior en la tubería podría ser una ventaja, pero en este caso, no se gana mucho. – Thomas

+0

sí, mis documentos de "estudiante" en realidad tienen un montón más campos, entonces estoy usando un proyecto para cortar los campos innecesarios. –