2011-03-15 27 views
18

Me gustaría devolver los documentos en un orden ordenado por el cual tiene el menor valor de foo.bar (que son objetos de matriz).Mongodb: ordenar documentos por objetos de matriz

Puedo hacer db.collection.find().sort({foo.0.bar: 1}), pero esto solo concuerda con el primer elemento de la matriz - y como puede ver en el siguiente examen ordenaría primero el elemento 1 (foo.0.bar = 5), cuando estoy buscando devolverlo item 2 primero (foo.2.bar = 4) ya que tiene el objeto con el valor más bajo.

{ 
    "name": "Item 1", 
    "foo": [ 
     { 
      "bar": 5 
     }, 
     { 
      "bar": 6 
     }, 
     { 
      "bar": 7 
     } 
    ] 
} 
{ 
    "name": "item 2", 
    "foo": [ 
     { 
      "bar": 6 
     }, 
     { 
      "bar": 5 
     }, 
     { 
      "bar": 4 
     } 
    ] 
} 
+0

db.collection.find() tipo ({foo.bar: 1}). – Troglo

Respuesta

0

No hay una manera directa de hacer esto en mongo. Debería usar map/reduce para recuperar el valor mínimo en cada matriz y luego ordenar por ese valor mínimo

+0

Gracias. ¿Pero cómo sería la función de mapa/reducir en el ejemplo? –

4

Una alternativa al uso de map/reduce, es almacenar el valor mínimo de la matriz como un campo separado en el documento que usted podría entonces ordenar. Cuando agrega a la matriz, también actualiza este campo si el nuevo valor es inferior al mínimo registrado actualmente.

p. Ej. el primer documento se convertiría en esto (nota "minbar añadió"):

{ 
    "name": "Item 1", 
    "minbar" : 5, 
    "foo": [ 
     { 
      "bar": 5, 
     } 
     { 
      "bar": 6, 
     } 
     { 
      "bar": 7, 
     } 
    ] 
} 
+0

Esta es una gran idea, y funcionaría bien en este ejemplo específico. Pero en un esquema más complejo en el que puede ser necesario hacer esto para varias matrices (es decir, mi esquema del mundo real), se volvería un poco desordenado. –

19

Parece mongo puede hacer esto.

Por ejemplo, si tengo los siguientes documentos:

{ a:{ b:[ {c:1}, {c:5 } ] } } 
{ a:{ b:[ {c:0}, {c:12} ] } } 
{ a:{ b:[ {c:4}, {c:3 } ] } } 
{ a:{ b:[ {c:1}, {c:9 } ] } } 

y ejecute los siguientes:

db.collection.find({}).sort({ "a.b.c":1 }); 
// produces: 
{ a:{ b:[ {c:0}, {c:12} ] } } 
{ a:{ b:[ {c:1}, {c:5 } ] } } 
{ a:{ b:[ {c:1}, {c:9 } ] } } 
{ a:{ b:[ {c:4}, {c:3 } ] } } 

db.collection.find({}).sort({ "a.b.c":-1 }); 
// produces: 
{ a:{ b:[ {c:0}, {c:12} ] } } 
{ a:{ b:[ {c:1}, {c:9 } ] } } 
{ a:{ b:[ {c:1}, {c:5 } ] } } 
{ a:{ b:[ {c:4}, {c:3 } ] } } 

Como se puede ver, el tipo de {"a.b.c":1} toma la min de todos los valores en el conjunto y ordena en eso, mientras que el orden por {"a.b.c":-1} toma el máximo de todos los valores.

+1

Ambas salidas producen el mismo resultado. ¿Es eso correcto? – Raman

+4

tienes que mirar de cerca. primer resultado es ascender 0, 1, 1, 3. segundo es descender 12,9,5,4. – rompetroll

4

Usted puede hacer una especie de este tipo con comando agregado desde la versión 2.2 mongo:

db.collection.aggregate([{$unwind: "$foo"}, 
    {$project: {bars:"$foo.bar"}}, 
    {$group: {_id:"$_id",min:{$min: "$bars"}}}, 
    {$sort: {min:1}}]) 
+0

¡Gracias por tu ejemplo! – Vor

Cuestiones relacionadas