我的用户集合有一个数组字段,其中包含子文档,如bellow:
"training" : [
{
"id" : ObjectId("5a01867959e2868ce09fbbc5"),
"startDate" : ISODate("2012-12-18T00:00:00.000Z"),
"endDate" : ISODate("2015-05-31T00:00:00.000Z"),
"inProgress" : false
},
{
"id" : ObjectId("5a01899959e2868ce09fbbc6"),
"startDate" : ISODate("2017-11-02T00:00:00.000Z"),
"endDate" : ISODate("2017-11-25T00:00:00.000Z"),
"inProgress" : false
},
{
"id" : ObjectId("5a01899959e2868ce09fbbc8"),
"startDate" : ISODate("2018-01-02T00:00:00.000Z"),
"endDate" : null,
"inProgress" : true
}
],
我想要的是:
1-获取每个用户在年,月和日的总培训期(假设第一次培训的git差异,{year: 2, month: 6, day: 12}
,第二次培训{year: 0, month: 0, day: 23}
,以及当前正在进行的培训的最后一次培训减去日期,应为{year: 0, month: 1, day: 15}
)
2-然后我应计算每个训练期的总和作为总训练期。
到目前为止我尝试过:
db.getCollection('user').aggregate([
{$unwind: "$training"},
{$project: {
duration: {"$divide":[{$subtract: ['$training.to', '$education.from'] }, 1000 * 60 * 60 * 24 * 365]}
}},
{$group: {
_id: '$_id',
"duration": {$sum: '$duration'}
}}]
])
但是这个有以下问题: 1-不能分别以所需格式计算每个训练周期,并且不能计算那些周期的总和作为总训练周期。因为训练期间可能会中断。 2-不能计算进行中的训练持续时间。
答案 0 :(得分:1)
添加了多个$addFields
阶段,以减少和计算每次培训和总培训的天数,月数和年数差异。
这里的假设是1个月= 30天总是
db.data.aggregate(
[
{
$addFields : {
trainingPeriod : {
$map : {
input : "$training",
as : "t",
in : {
year: {$subtract: [{$year : {$ifNull : ["$$t.endDate", new Date()]}}, {$year : "$$t.startDate"}]},
month: {$subtract: [{$month : {$ifNull : ["$$t.endDate", new Date()]}}, {$month : "$$t.startDate"}]},
dayOfMonth: {$subtract: [{$dayOfMonth : {$ifNull : ["$$t.endDate", new Date()]}}, {$dayOfMonth : "$$t.startDate"}]}
}
}
}
}
},
{
$addFields : {
trainingPeriod : {
$map : {
input : "$trainingPeriod",
as : "d",
in : {
year: "$$d.year",
month: {$cond : [{$lt : ["$$d.dayOfMonth", 0]}, {$subtract : ["$$d.month", 1]}, "$$d.month" ]},
day: {$cond : [{$lt : ["$$d.dayOfMonth", 0]}, {$add : [30, "$$d.dayOfMonth"]}, "$$d.dayOfMonth" ]}
}
}
}
}
},
{
$addFields : {
trainingPeriod : {
$map : {
input : "$trainingPeriod",
as : "d",
in : {
year: {$cond : [{$lt : ["$$d.month", 0]}, {$subtract : ["$$d.year", 1]}, "$$d.year" ]},
month: {$cond : [{$lt : ["$$d.month", 0]}, {$add : [12, "$$d.month"]}, "$$d.month" ]},
day: "$$d.day"
}
}
}
}
},
{
$addFields : {
total : {
$reduce : {
input : "$trainingPeriod",
initialValue : {year : 0, month : 0, day : 0},
in : {
year: {$add : ["$$this.year", "$$value.year"]},
month: {$add : ["$$this.month", "$$value.month"]},
day: {$add : ["$$this.day", "$$value.day"]}
}
}
}
}
},
{
$addFields : {
total : {
year : "$total.year",
month : {$add : ["$total.month", {$floor : {$divide : ["$total.day", 30]}}]},
day : {$mod : ["$total.day", 30]}
}
}
},
{
$addFields : {
total : {
year : {$add : ["$total.year", {$floor : {$divide : ["$total.month", 12]}}]},
month : {$mod : ["$total.month", 12]},
day : "$total.day"
}
}
}
]
).pretty()
结果
{
"_id" : ObjectId("5a87fcf68a2c0b7c0666140f"),
"training" : [
{
"id" : ObjectId("5a01867959e2868ce09fbbc5"),
"startDate" : ISODate("2012-12-18T00:00:00Z"),
"endDate" : ISODate("2015-05-31T00:00:00Z"),
"inProgress" : false
},
{
"id" : ObjectId("5a01899959e2868ce09fbbc6"),
"startDate" : ISODate("2017-11-02T00:00:00Z"),
"endDate" : ISODate("2017-11-25T00:00:00Z"),
"inProgress" : false
},
{
"id" : ObjectId("5a01899959e2868ce09fbbc8"),
"startDate" : ISODate("2018-01-02T00:00:00Z"),
"endDate" : null,
"inProgress" : true
}
],
"trainingPeriod" : [
{
"year" : 2,
"month" : 5,
"day" : 13
},
{
"year" : 0,
"month" : 0,
"day" : 23
},
{
"year" : 0,
"month" : 1,
"day" : 16
}
],
"total" : {
"year" : 2,
"month" : 7,
"day" : 22
}
}
>