Эта агрегация дает желаемый результат Allocations
. Использование следующего примера входного документа :
{
_id : ObjectId("5e42154155533a54ed5fb852"),
Id: 1,
StartDate: ISODate("2020-01-30"),
EndDate: ISODate("2020-02-05"),
TotalValue: 100
}
Запрос:
db.collection.aggregate( [
{
$addFields: {
daysArr: {
$range: [ 0, { $add: [ { $divide: [ { $subtract: [ "$EndDate", "$StartDate" ] }, 86400000 ] } , 1 ] } ]
}
}
},
{
$addFields: {
Allocations: {
$map: {
input: "$daysArr",
in: {
date: { $add: [ "$StartDate", { $multiply: [ 86400000, "$$this" ] } ] },
val: { $divide: [ "$TotalValue", { $add: [ { $divide: [ { $subtract: [ "$EndDate", "$StartDate" ] }, 86400000 ] }, 1 ] } ] }
}
}
}
}
},
{
$project: { daysArr: 0 }
}
] )
Выходной документ:
{
"_id" : ObjectId("5e42154155533a54ed5fb852"),
"Id" : 1,
"StartDate" : ISODate("2020-01-30T00:00:00Z"),
"EndDate" : ISODate("2020-02-05T00:00:00Z"),
"TotalValue" : 100,
"Allocations" : [
{
"date" : ISODate("2020-01-30T00:00:00Z"),
"val" : 14.285714285714286
},
{
"date" : ISODate("2020-01-31T00:00:00Z"),
"val" : 14.285714285714286
},
{
"date" : ISODate("2020-02-01T00:00:00Z"),
"val" : 14.285714285714286
},
{
"date" : ISODate("2020-02-02T00:00:00Z"),
"val" : 14.285714285714286
},
{
"date" : ISODate("2020-02-03T00:00:00Z"),
"val" : 14.285714285714286
},
{
"date" : ISODate("2020-02-04T00:00:00Z"),
"val" : 14.285714285714286
},
{
"date" : ISODate("2020-02-05T00:00:00Z"),
"val" : 14.285714285714286
}
]
}
[Обновлено в соответствии с дополнением от 17 февраля]
Это объединение будет обрабатывать два типа входных документов:
{
"_id" : ObjectId("5e4a16e96d13751bfb64572d"),
"Id" : 1,
"StartDate" : ISODate("2019-01-01T00:00:00Z"),
"EndDate" : ISODate("2019-12-12T00:00:00Z"),
"TotalValue" : 3500,
"Allocations" : [
{
"startDate" : ISODate("2019-01-01T00:00:00Z"),
"endDate" : ISODate("2019-01-10T00:00:00Z"),
"val" : 2000
},
{
"startDate" : ISODate("2019-01-11T00:00:00Z"),
"endDate" : ISODate("2019-01-12T00:00:00Z"),
"val" : 1500
}
]
}
{
"_id" : ObjectId("5e42154155533a54ed5fb852"),
"Id" : 11,
"StartDate" : ISODate("2020-02-01T00:00:00Z"),
"EndDate" : ISODate("2020-02-05T00:00:00Z"),
"TotalValue" : 100
}
Запрос агрегации:
db.collection.aggregate( [
{
$addFields: {
Allocations: {
$ifNull: [
"$Allocations",
[ { startDate: "$StartDate", endDate: "$EndDate", val: "$TotalValue" } ]
]
}
}
},
{
$addFields: {
Allocations: {
$map: {
input: "$Allocations",
in: {
$mergeObjects: [
"$$this",
{ range: {
$range: [
0,
{ $add: [ { $divide: [ { $subtract: [ "$$this.endDate", "$$this.startDate" ] }, 86400000 ] } , 1 ] }
]
} }
]
}
}
}
}
},
{
$unwind: "$Allocations"
},
{
$addFields: {
Allocations: {
$map: {
input: "$Allocations.range",
in: {
date: { $add: [ "$Allocations.startDate", { $multiply: [ 86400000, "$$this" ] } ] },
val: { $divide: [ "$Allocations.val", { $size: "$Allocations.range" } ] }
}
}
}
}
},
{
$group: {
_id: "$_id",
Allocations: { $push: "$Allocations" },
doc: { $first: "$$ROOT" }
}
},
{
$addFields: {
"doc.Allocations": {
$reduce: {
input: "$Allocations", initialValue: [ ],
in: { $concatArrays : ["$$value", "$$this"] }
}
}
}
},
{
$replaceRoot: { newRoot: "$doc" }
}
] )