2017-04-23 55 views
0

我是Mongodb和NoSQL的新手,我試圖使用mongodbs聚合函數來將數據從一個集合中插入到另一個集合中。原始集合的一個例子是這樣的:

原始集合 { supplier: 'aldi', timestamp: '1492807458', user: '[email protected]', hasBeenAggregated:false, items:[{ name: 'butter', supplier: 'aldi', expiry: '1492807458', amount: 454, measureSymbol: 'g', cost: 2.19 },{ name: 'milk', supplier: 'aldi', expiry: '1492807458', amount: 2000, measureSymbol: 'ml', cost: 1.49 }] }

輸出我想實現將是一個例子:

新集合 { user:'[email protected]', amount: 3.68, isIncome: false, title: 'food_shopping', timestamp: '1492807458' }

我正在使用的聚合函數是:

聚集 var result = db.runCommand({ aggregate: 'food_transactions', pipeline: [ {$match: {hasBeenAggregated: false}}, {$unwind: '$items'}, {$group:{_id: '$_id',amount:{$sum: '$items.cost'}}}, {$project: { _id:0, user:1, amount:1, isIncome: {$literal: false}, title:{$literal: 'food_shopping'}, timestamp:1 }} ] }); printjson(result)

此聚合函數不返回usertimestamp領域。相反,我得到下面的輸出:

輸出 { "amount" : 3.6799999999999997, "isIncome" : false, "title" : "food_shopping" }

如果我不組的結果,並執行在$project階段的計算,字段都正確地預測,但很明顯,有一個爲items數組中的每個子文檔創建的新文檔,這相當於打破了聚合的目的。

我在做什麼錯?

回答

2

更新您的$group管道,包括你想進一步向下突出管道中的各個領域。

要包括用戶字段,你可以使用$first

{$group:{_id: '$_id', user:{$first:'$user`}, amount:{$sum: '$items.cost'}}}, 

此外,如果你是3.4版本,您可以簡化聚集到下面。

使用$reduce總結一個文檔中的所有item的成本。對於所有文件,您可以在$reduce之後添加$group

db.collection.aggregate([ 
     {$match: {hasBeenAggregated: false}}, 
     {$project: { 
      _id:0, 
      user:1, 
      amount: { 
       $reduce: { 
       input: "$items", 
       initialValue: 0, 
       in: { $add : ["$$value", "$$this.cost"] } 
       } 
      }, 
      isIncome: {$literal: false}, 
      title:{$literal: 'food_shopping'}, 
      timestamp:1 
     }} 
    ])