2011-03-15 4 views
18

Je voudrais retourner les documents dans un ordre trié par qui contient la valeur la plus basse foo.bar (qui sont des objets de tableau).Mongodb: trier les documents par objets de tableau

Je peux faire db.collection.find().sort({foo.0.bar: 1}), mais cela ne correspond qu'au premier élément du tableau - et comme vous pouvez le voir dans l'exemple ci-dessous, je vais trier l'item 1 en premier (foo.0.bar = 5), où je cherche à revenir article 2 premier (foo.2.bar = 4) car il a l'objet avec la plus faible valeur.

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

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

Répondre

0

Il n'existe aucun moyen direct de le faire dans mongo. Vous auriez besoin d'utiliser map/reduce pour récupérer la valeur minimale dans chaque tableau et ensuite trier de cette valeur min

+0

Merci. Mais à quoi ressemblerait la fonction map/reduce dans l'exemple? –

4

Une alternative à l'utilisation de map/reduce est de stocker la valeur min de la matrice comme champ séparé dans le document que vous pourriez ensuite commander. Lorsque vous ajoutez au tableau, vous mettez également à jour ce champ si la nouvelle valeur est inférieure au minimum actuellement enregistré.

par exemple. votre premier document deviendrait cette (note "minbar ajouté"):

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

Ceci est une excellente idée - et fonctionnerait bien dans cet exemple spécifique. Mais sur un schéma plus complexe où cela peut être nécessaire pour plusieurs tableaux (c'est-à-dire mon schéma du monde réel), cela deviendrait un peu compliqué. –

19

Il semble mongo peut faire.

Par exemple, si j'ai les documents suivants:

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

Et exécutez la commande suivante:

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 } ] } } 

Comme vous pouvez le voir, le genre par {"a.b.c":1} prend la min de toutes les valeurs dans le tableau et trie sur cela, alors que le tri par {"a.b.c":-1} prend le max de toutes les valeurs.

+1

Vos deux sorties produisent le même résultat. Est-ce exact? – Raman

+4

vous devez regarder de près. le premier résultat est 0, 1, 1, 3. Le second est descendant 12,9,5,4. – rompetroll

4

Vous pouvez faire une telle sorte avec la commande globale de la version 2.2 mongo:

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

Merci pour votre exemple! – Vor

Questions connexes