Агрегирование данных в MongoDB на основе значений свойств - PullRequest
0 голосов
/ 06 января 2019

Я использую MongoDB 3.4, и мне нужно создать фильтр запросов для выборки данных из моей коллекции монго (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 голосов
/ 06 января 2019

Вы можете попробовать агрегацию ниже, чтобы получить результат, логика заключается в использовании $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
                }
        ]
}
>
0 голосов
/ 06 января 2019

Я не уверен, что такая агрегация возможна даже в mongodb. Похоже на типичную бизнес-логику для серверной стороны, и поэтому я хотел бы предложить извлечь соответствующие данные на сервер и выполнить все вычисления там. Таким образом, все гораздо менее сложно и без потери производительности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...