根据属性值在MongoDB中聚合数据

时间:2019-01-06 12:05:08

标签: mongodb aggregation-framework

我正在使用MongoDB 3.4,我需要创建一个查询过滤器以从我的mongo集合(ProductionEventsCollection)中获取数据。 有些值是“ 即时”计算的。

由于这些记录是基于事件的,并且将来的值取决于过去的值,因此,如果过去更改某个值,则会影响将来的总和。

我有一个集合,其属性如下所示:

[{
 _id: "5bfc2a16b4f11f3760ed4b64",
 piece_id: "12345",
 finish_date: "2018-11-26T17:15:09.795Z",
 total_produced: 500
},
{
 _id: "5bfc2a16b4f11f3760ed4b65",
 piece_id: "12345",
 finish_date: "2018-11-27T17:15:09.795Z",
 total_produced: 750
},
{
 _id: "5bfc2a16b4f11f3760ed4b66",
 piece_id: "12345",
 finish_date: "2018-11-28T17:15:09.795Z",
 total_produced: 250
}]

想法是获得这样的收藏:

[{
 _id: "5bfc2a16b4f11f3760ed4b64",
 piece_id: "12345",
 finish_date: "2018-11-26T17:15:09.795Z",
 previous_value: 0,
 total_produced: 500,
 new_value: 500
},
{
 _id: "5bfc2a16b4f11f3760ed4b65",
 piece_id: "12345",
 finish_date: "2018-11-27T17:15:09.795Z",
 previous_value: 500,
 total_produced: 750,
 new_value: 1250
},
{
 _id: "5bfc2a16b4f11f3760ed4b66",
 piece_id: "12345",
 finish_date: "2018-11-28T17:15:09.795Z",
 previous_value: 1250,
 total_produced: 250,
 new_value: 1500
}]

基于finish_date属性,我应该能够计算到该日期之前的previous_value和,而new_value将是先前计算的总和加上total_produced

上一个值

previous_value = SUM(past total_produced) until finish_date

新价值

new_value = previous_value + total_produced

基于这些集合值,我需要返回一个json数组,因为我将允许用户下载电子表格。

2 个答案:

答案 0 :(得分:1)

您可以尝试在汇总下面获取结果,逻辑是使用$reduce来计算运行总计

聚合管道

db.t32.aggregate([
    {$group : {_id : "$piece_id", data : {$push : "$$ROOT"}}}, 
    {$addFields : {data : 
        {$reduce : {
            input : "$data", 
            initialValue : [{previous_value :  0, total_produced : 0, new_value : 0}], 
            in : {$concatArrays : 
                [ "$$value",[{$mergeObjects : ["$$this", { previous_value : {$arrayElemAt : ["$$value.new_value", -1]} , total_produced : "$$this.total_produced", new_value : {$sum : ["$$this.total_produced",{$arrayElemAt : ["$$value.new_value", -1]}]}}]}]]
            }
        }}
    }},
    {$addFields : {data : {$slice : ["$data", 1, {$size : "$data"}]}}}
]).pretty()

样品采集

> db.t32.find()
{ "_id" : "5bfc2a16b4f11f3760ed4b64", "piece_id" : "12345", "finish_date" : "2018-11-26T17:15:09.795Z", "total_produced" : 500 }
{ "_id" : "5bfc2a16b4f11f3760ed4b65", "piece_id" : "12345", "finish_date" : "2018-11-27T17:15:09.795Z", "total_produced" : 750 }
{ "_id" : "5bfc2a16b4f11f3760ed4b66", "piece_id" : "12345", "finish_date" : "2018-11-28T17:15:09.795Z", "total_produced" : 250 }

汇总结果

> db.t32.aggregate([
... {$group : {_id : "$piece_id", data : {$push : "$$ROOT"}}},
... {$addFields : {data :
... {$reduce : {
... input : "$data",
... initialValue : [{previous_value :  0, total_produced : 0, new_value : 0}],
... in : {$concatArrays :
... [ "$$value",[{$mergeObjects : ["$$this", { previous_value : {$arrayElemAt : ["$$value.new_value", -1]} , total_produced : "$$this.total_produced", new_value : {$sum : ["$$this.total_produced",{$arrayElemAt : ["$$value.new_value", -1]}]}}]}]]
... }
... }}
... }},
... {$addFields : {data : {$slice : ["$data", 1,1000]}}}
... ]).pretty()
{
        "_id" : "12345",
        "data" : [
                {
                        "_id" : "5bfc2a16b4f11f3760ed4b64",
                        "piece_id" : "12345",
                        "finish_date" : "2018-11-26T17:15:09.795Z",
                        "total_produced" : 500,
                        "previous_value" : 0,
                        "new_value" : 500
                },
                {
                        "_id" : "5bfc2a16b4f11f3760ed4b65",
                        "piece_id" : "12345",
                        "finish_date" : "2018-11-27T17:15:09.795Z",
                        "total_produced" : 750,
                        "previous_value" : 500,
                        "new_value" : 1250
                },
                {
                        "_id" : "5bfc2a16b4f11f3760ed4b66",
                        "piece_id" : "12345",
                        "finish_date" : "2018-11-28T17:15:09.795Z",
                        "total_produced" : 250,
                        "previous_value" : 1250,
                        "new_value" : 1500
                }
        ]
}
>

答案 1 :(得分:0)

我不确定在mongodb中是否可以进行这种聚合。 听起来像是服务器端的典型业务逻辑,因此我建议将相关数据提取到服务器并在那里进行所有计算。这样一来,事情变得简单得多,并且没有任何性能损失。