2017-07-24 136 views
0

我試圖獲取數組內的特定字段的總和。問題是,該數組也在另一個數組中。我的文件如下(簡化):MongoDB Aggregation - 嵌套數組的總和值

{ 
    "nome": "test-1" 
    "notas": [{ 
     "numero_fiscal": "0001", 
     "valores": { 
      "portal": 1000, 
      "arquivo": 1000 
     }, 
     "abatimentos": [{ 
      "valor": 250, 
      "tipo": "TIPO 1" 
     }, { 
      "valor": 250, 
      "tipo": "TIPO 2" 
     }] 
    }, { 
     "numero_fiscal": "0002", 
     "valores": { 
      "portal": 2000, 
      "arquivo": 2000 
     }, 
     "abatimentos": [{ 
      "valor": 500, 
      "tipo": "TIPO 1" 
     }, { 
      "valor": 500, 
      "tipo": "TIPO 2" 
     }] 
    }] 
} 

我希望我的輸出是這樣的:

{ 
    "_id": "resumo", 
    "total_notas": 2, // this is the counter for the array "notas" 
    "soma_portal": 3000, // this is the sum of the "valores.portal" of all "notas" 
    "soma_arquivo": 3000, // this is the sum of the "valores.arquivo" of all "notas" 
    "soma_abatimento": 1500 // this is the sum of all the "abatimentos.valor" from all the "notas" 
} 

我曾嘗試以下聚合(除其他外,但結果總是相同) :

Notas.aggregate() 
.match(my_query) 
.unwind('notas') // unwinding 'notas' array 
.group({ 
    '_id': 'resumo', 
    'total_notas': { '$sum': 1 }, 
    'abatimentos': { '$push': '$notas.abatimentos' }, 
    'soma_portal': { '$sum': { '$notas.valores.portal' } }, 
    'soma_arquivo': { '$sum': { '$notas.valores.arquivo' } } 
}) 
.unwind('$abatimentos') 
.group({ 
    '_id': '$_id', 
    'total_notas': { '$first': '$total_notas' }, 
    'soma_portal': { '$first': '$soma_portal' }, 
    'soma_arquivo': { '$first': '$soma_arquivo' }, 
    'soma_abatimento': { '$sum': '$abatimentos.valor' } 
}) 

這給了我幾乎所有的東西我想正確的,但 'soma_abatimento' 始終爲0,而​​不是1500

我在正確的道路上嗎?或者這是不應該在數據庫查詢上完成的事情?

回答

2

在您當前的版本中,您需要添加一個雙倍$展開,因爲正如您已經正確識別的那樣,在您的第一個$組後有一個數組。

這是一個稍作修改的版本,可以產生預期的結果。

db.Notas.aggregate([{ 
    $unwind: "$notas" 
}, { 
    $group: { 
    _id: "resumo", 
    total_notas: { $sum: 1 }, 
    soma_portal: { $sum: "$notas.valores.portal" }, 
    soma_arquivo: { $sum: "$notas.valores.arquivo" }, 
    abatimentos: { $push: "$notas.abatimentos" } 
    } 
}, { 
    $unwind: "$abatimentos" 
}, { 
    $unwind: "$abatimentos" 
}, { 
    $group: { 
    _id: "$_id", 
    total_notas: { $first: "$total_notas" }, 
    soma_portal: { $first: "$soma_portal" }, 
    soma_arquivo: { $first: "$soma_arquivo" }, 
    soma_abatimentos: { $sum: "$abatimentos.valor" } 
    } 
}]) 

如果你能夠使用MongoDB的> = 3.4,我建議你採用不同的方法,這將減少文件大小和使用$排除超過一個$放鬆身心的需要減少在MongoDB中添加3.4

db.Notas.aggregate([{ 
    $unwind: "$notas" 
}, { 
    $project: { 
    _id: 0, 
    portal: "$notas.valores.portal", 
    arquivo: "$notas.valores.arquivo", 
    abatimentos: { 
     $reduce: { 
     input: "$notas.abatimentos", 
     initialValue: 0, 
     in: { $add: ["$$value", "$$this.valor"] } 
     } 
    } 
    } 
}, { 
    $group: { 
    _id: "resumo", 
    total_notas: { $sum: 1 }, 
    soma_portal: { $sum: "$portal" }, 
    soma_arquivo: { $sum: "$arquivo" }, 
    soma_abatimentos: { $sum: "$abatimentos" } 
    } 
}]) 
+0

Thanks tkbyte,that worked perfect! MongoDB> = 3.4更好,所以謝謝你提供這兩種方式。 –