2017-12-21 8 views
3

I die folgenden Datensätze:MongoDB Aggregation ohne Duplizierung

{ "_id" : 1, "c" : 120, "b" : [ { "f1" : 10 }, { "f1" : 10 } ] } 
{ "_id" :2, "c" : 5, "b" : [ { "f1" : 10 }, { "f1" : 10 } ] } 

ich brauche die Ausgabe auf diese Weise:

{ "_id" : 1, 'total':140} 
{ "_id" :2, 'total':25 } 

wo total = Summe des Wertes in 'C' mit der Summe der Werte in F1 für den gleichen Rekord.

Wenn ich entspannen, das Feld ‚b‘ es schafft zwei Dokumente mit derselben ID und somit Daten dupliziert und wenn ich es zusammenzufassen, ich bekomme:

db.test2.aggregate([ 
    {'$unwind':'$b'}, 
    {'$project':{'total':{'$add':['$c','$b.f1']}}}, 
    {'$group':{'_id':'$_id', 'total':{'$sum':'$total'}}} 
]) 

Ausgänge:

{ "_id" : 1, 'total':260} 
{ "_id" :2, 'total':30 } 

(nicht das, was ich wollte, wie es beim Abwickeln der Vervielfältigung durch 120 und 5 wieder insgesamt hinzugefügt)

so habe ich versucht:

db.test2.aggregate([ 
    {'$unwind':'$b'}, 
    {'$group':{'_id':'$_id', 'c':{'$push': '$c'},'f1':{'$sum':'$b.f1'}}}, 
    {'$project':{'total':{'$add':[{'$arrayElemAt':['$c',0]},'$f1']}}} 
]) 

Ausgänge:

{ "_id" : 1, 'total':140} 
{ "_id" :2, 'total':25 } 

(was ich wollte)

Gibt es eine andere Möglichkeit, dies zu erreichen?

Antwort

2

Sie können unter Abfrage versuchen. Der Summenoperator berechnet zuerst die Summe im Array, gefolgt von add, um die Summe mit dem anderen Feld zu berechnen.

db.test2.aggregate([{ 
    $project: { 
     total: {"$add":["$c", {"$sum":"$b.f1"}]} 
    } 
}] 
+0

einfach und elegant – Adarsh

1

Eine Alternative:

db.test2.aggregate([{ 
     $project: { 
      _id: 0, 
      c: "$c", 
      b: { 
       $reduce: { 
        input: "$b.f1", 
        initialValue: 0, 
        in: { 
         $add: ["$$value", "$$this"] 
        } 
       } 
      } 
     } 
    }, 
    { 
     $project: { 
      _id: 0, 
      total: { 
       $sum: ["$c", "$b"] 
      } 
     } 
    } 
]) 

diesem Ergebnis führen würde:

{ 
    "total" : 140 
} 
{ 
    "total" : 25 
} 

Wenn Sie das Feld benötigen _id dann ersetzen Sie die _id: 0 in beide $project-_id: 1

, dass dieses Ergebnis führen würde :

{ 
    "_id" : 1, 
    "total" : 140 
} 
{ 
    "_id" : 2, 
    "total" : 25 
} 
+0

wäre dies skalierbar, wenn b eine beliebige Anzahl von {'f1': 10} hat? – Adarsh

+0

@Adarsh ​​Ich aktualisierte die Antwort. Diese Lösung ist noch besser skalierbar –

+0

Nun, das ist golden :) – Adarsh