2014-04-22 2 views
0

J'ai besoin d'agréger les données suivantesmongo globale avec plusieurs types d'agrégation

- Country: One, Car: Volvo, Name: Smith, Price: 100 
- Country: One, Car: BMW, Name: Smith, Price: 200 
- Country: Two, Car: Romeo, Name: Joe, Price: 50 
- Country: Two, Car: KIA, Name: Joe, Price: 110 
- Country: Two, Car: KIA, Name: Joe, Price: 90 

(noms sont uniques, chacun possède des voitures dans un seul pays)

Les résultats, je pense (pluralisation n'est pas requise):

- Name: Smith, Type: Volvos, Country: One, Val: 1 // Count of car-type 
- Name: Smith, Type: BMWs, Country: One, Val: 1 
- Name: Smith, Type: Total, Country: One, Val: 2 // Count of all his cars 
- Name: Smith, Type: Price, Country: One, Val: 300 // Total car price 
- Name: Joe, Type: Romeos, Country: Two, Val: 1 
- Name: Joe, Type: KIAs, Country: Two, Val: 2 
- Name: Joe, Type: Total, Country: Two, Val: 3 
- Name: Joe, Type: Price, Country: Two, Val: 250 

Par exemple ceci est une version de données pivotized pour construire un rapport

Country | Name | Volvos | BMWs | Romeos | KIAs | Total | Price 
---------------------------------------------------------------- 
One  | Smith |  1 | 1 |  |  |  2 | 300 
---------------------------------------------------------------- 
Two  | Joe |  |  |  1 | 2 |  3 | 250 
     | Other |  ? | ? |  ... etc 

Je pense si le cadre d'agrégation mongo peut gérer cela, ou devrais-je aller hardcore carte-reduce?

+0

Essayez cette méthode d'agrégation. bcoz si les données deviennent grandes, alors il est difficile d'aller sur la carte hardcore réduire – Mayuri

+0

@Mayuri Carte et réduisent l'agrégation sont deux choses différentes pour deux pruposes totalement différentes, MR ne doivent pas être exécutés en ligne à votre propre application par exemple – Sammaye

+0

La question principale est que Je ne suis pas sûr que cela soit implémentable avec AF. –

Répondre

0

L'agrégation devrait être très bien pour cela. 2 commandes comme Easiest séparées ... Si votre collection a été appelé voitures que vous pouvez exécuter quelque chose comme ceci:

db.cars.aggregate([{$group:{_id:{"Country":"$Country","Name":"$Name"},"sum":{$sum:1},"price":{$sum:"$Price"}}}]) 


db.cars.aggregate([{$group:{_id:{"Country":"$Country","Name":"$Name","Car":"$Car"},"sum":{$sum:1},"price":{$sum:"$Price"}}}]) 
+0

Les résultats de votre commande ne sont pas ce que je m'attendais: il n'y a pas * compte de toutes les voitures par personne *, et aucun * prix total de la voiture par personne *. –

+0

@RustemMustafin mis à jour (Voitures retirées de _id) –

+0

Il nous manque maintenant des comptes de voitures par personne avec le type donné (voir, Joe a 2 KIA et 3 voitures au total). –

1

Il pourrait y avoir un truc à faire cela, cependant, avec un nombre variable de types je ne crois pas vous pouvez obtenir ceci dans une requête d'agrégation, cependant, vous pouvez obtenir la table entière en deux.

Je dois mentionner que les totaux peuvent être calculés côté client qui devrait être assez rapide aussi bien.

Je devrais également noter que le cadre d'agrégation n'a actuellement aucun moyen de "fusionner" deux sorties: http://docs.mongodb.org/manual/reference/operator/aggregation/out/, mais vous pouvez trier les deux résultats à commander les mêmes.

D'abord, vous voulez votre total (si vous faites cela grâce à un cadre d'agrégation):

db.cars.aggregate({ 
    {$group: { 
     _id: { 
      Country: '$country', 
      Name: '$Name' 
     }, 
     car_count: {$sum: 1}, 
     value_total: {$sum: '$Val'} 
    }}, 
    {$sort: {_id: 1}} // we now sort by the country and name 
}) 

Alors maintenant, vous voulez que vos totaux par voiture:

db.cars.aggregate({ 
    {$group: { 
     _id: { 
      Country: '$country', 
      Name: '$Name', 
      Type: '$Type' 
     }, 
     sort_key: { // We add this so we can sort the same as the totals 
      Country: '$Country', 
      Name: '$Name' 
     }, 
     car_count: {$sum: 1}, 
     value_total: {$sum: '$Val'} 
    }}, 
    {$sort: {sort_key: 1}} // we now sort by the country and name 
}) 

Maintenant ce que vous pouvez, en JavaScript, par exemple, itère le premier ensemble de résultats, vos totaux, en répétant les résultats détaillés de l'autre agrégation dans une boucle imbriquée.

Ce serait probablement plus rapide que la carte Réduire, mais une autre alternative consiste à mettre à jour la collection agrégée une fois si souvent en utilisant la carte Réduire et juste de là choisir. Cela signifie que les résultats ne seront pas en temps réel (peut-être retardé de 5 minutes) mais ce sera super rapide.

2

Pas exactement le résultat que vous prescrivez, mais en fait dans une sorte de façon MongoDB:

db.cars.aggregate([ 
    { "$group": { 
     "_id": { 
      "name": "$Name", 
      "type": "$Car" 
     }, 
     "Country": { "$first": "$Country" }, 
     "CarCount": { "$sum": 1 }, 
     "TotalPrice": { "$sum": "$Price" } 
    }}, 
    { "$group": { 
     "_id": "$_id.name", 
     "cars": { 
      "$push": { 
       "type": "$_id.type", 
       "country": "$Country", 
       "carCount": "$CarCount", 
       "TotalPrice": "$TotalPrice" 
      } 
     }, 
     "TotalPrice": { "$sum": "$TotalPrice" } 
    }} 
]) 

Ce qui vous donne:

{ 
    "_id" : "Smith", 
    "cars" : [ 
      { 
        "type" : "BMW", 
        "country" : "One", 
        "carCount" : 1, 
        "TotalPrice" : 200 
      }, 
      { 
        "type" : "Volvo", 
        "country" : "One", 
        "carCount" : 1, 
        "TotalPrice" : 100 
      } 
    ], 
    "TotalPrice" : 300 
} 
{ 
    "_id" : "Joe", 
    "cars" : [ 
      { 
        "type" : "KIA", 
        "country" : "Two", 
        "carCount" : 2, 
        "TotalPrice" : 200 
      }, 
      { 
        "type" : "Romeo", 
        "country" : "Two", 
        "carCount" : 1, 
        "TotalPrice" : 50 
      } 
    ], 
    "TotalPrice" : 250 
} 
+0

Hé, mayabe Je peux aussi pousser {type: 'Total'} dans les voitures, et les résultats se déroulent pour obtenir exactement la collection correspondante? Est-ce possible? –

+0

@RustemMustafin pas vraiment il a couru dans le même problème que moi, si vous avez une voiture forme deux pays différents par le même gars ces totaux ne correspondent pas – Sammaye

+0

@Sammaye c'est valide, parce que j'ai déclaré que «chacun possède voitures dans un seul pays » –