2017-07-24 101 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更好,所以谢谢你提供这两种方式。 –