我有一个shifts
集合,如下所示
{
"_id" : ObjectId("5885a1108c2fc432d649647d"),
"from" : ISODate("2017-01-24T06:21:00.000Z"), //can be weekday, sat, sun
"to" : ISODate("2017-01-24T08:21:00.000Z"),
"jobId" : ObjectId("586d7d6acfc7e05669d6e2c8"),
"hourlyRate" : 32 //this wil vary based on **from** field
}
{
"_id" : ObjectId("5885a1108c2fc432d649647e"),
"from" : ISODate("2017-01-25T06:21:00.000Z"),
"to" : ISODate("2017-01-25T08:21:00.000Z"),
"jobId" : ObjectId("586d7d6acfc7e05669d6e2c8"),
"hourlyRate" : 32
}
{
"_id" : ObjectId("5885a1108c2fc432d649647f"),
"from" : ISODate("2017-01-26T06:21:00.000Z"),
"to" : ISODate("2017-01-26T08:21:00.000Z"),
"jobId" : ObjectId("586d7d6acfc7e05669d6e2c8"),
"hourlyRate" : 32
}
我希望能够生成像这样的输出
工作日或周六或周日可以从from
字段派生。对于工作日,需要对周一至周五的所有日期进行分组。
可以通过从from
中减去to
来获得小时数。
所以,我认为需要完成以下工作,但我无法在MongoDB中实现
jobId
分组,从from
(也包括所有工作日组)中逐日分组,并通过减去from
和to
获得提取的小时数。我发现了一些类似的问题,但我无法将其应用到我的情况中
mongodb group values by multiple fields
Mongodb Aggregation Framework | Group over multiple values?
How to group by multiple columns and multiple values in mongodb
使用案例:
当用户访问名为“收入”的页面时,我需要向他显示每个作业和总收入的上周收入(然后他可以更改日期范围)。所以,我打算将节目分成每个工作,进一步分为工作日,周六和周日收入以及 THAT 工作的总收入和工作时间。最终总收入是所有个人工作收入的总和。
P.S我正在使用MongoDB 3.4
答案 0 :(得分:1)
按照以下聚合查询:
db.shifts.aggregate([{
//this get the day of week and converts them into sunday, saturday
$project: {
jobId:1,
hourlyRate:1,
dayOfWeek: { $dayOfWeek: "$from" },
workedHours: {$divide:[{ $subtract: ["$to", "$from"] }, 3600000]},
saturday:{$floor: {$divide:[{ $dayOfWeek: "$from" }, 7]}},
sunday:{$floor: {$divide:[{$abs:{$subtract:[{ $dayOfWeek: "$from" }, 7]}}, 6]}},
}
}, {
//based on the values of sunday and saturday gets the value of weekday
$project: {
jobId:1,
workedHours:1,
hourlyRate:1,
saturday:1,
sunday: 1,
weekday:{$abs: {$add:["$sunday","$saturday", -1]}},
}
}, {
//here calculates the earnings for each job
$group:{
_id:"$jobId",
sundayEarnings:{$sum: {$multiply:["$sunday", "$hourlyRate", "$workedHours"]}},
saturdayEarnings:{$sum: {$multiply:["$saturday", "$hourlyRate", "$workedHours"]}},
weekdayEarnings:{$sum: {$multiply:["$weekday", "$hourlyRate", "$workedHours"]}},
totalEarnings: {$sum:{$multiply:["$hourlyRate", "$workedHours"]}},
totalWorkedHours: {$sum: "$workedHours"}
}
}, {
//and finally calculates the total jobs earnings
$group:{
_id:null,
jobs:{$push:{
jobId: "$_id",
sundayEarnings: "$sundayEarnings",
saturdayEarnings: "$saturdayEarnings",
weekdayEarnings: "$weekdayEarnings",
totalEarnings: "$totalEarnings",
totalWorkedHours: "$totalWorkedHours"
}},
totalJobsEarning: {$sum: "$totalEarnings"}
}
}])
$project
聚合通过进行多次算术计算,根据saturday
值为sunday
和dayOfWeek
提供 0或1 值$project
聚合根据weekday
和saturday
值计算sunday
的值。$group
计算每项工作中每天的收入。$group
聚合计算所有工作的收入总和。 <强>测试强>
这是我的意见:
{
"_id" : ObjectId("5885a1108c2fc432d649647d"),
"from" : ISODate("2017-01-24T06:21:00Z"),
"to" : ISODate("2017-01-24T08:21:00Z"),
"jobId" : ObjectId("586d7d6acfc7e05669d6e2c8"),
"hourlyRate" : 32
}
{
"_id" : ObjectId("5885a1108c2fc432d649647e"),
"from" : ISODate("2017-01-25T06:21:00Z"),
"to" : ISODate("2017-01-25T08:21:00Z"),
"jobId" : ObjectId("586d7d6acfc7e05669d6e2c8"),
"hourlyRate" : 32
}
{
"_id" : ObjectId("5885a1108c2fc432d649647f"),
"from" : ISODate("2017-01-26T06:21:00Z"),
"to" : ISODate("2017-01-26T08:21:00Z"),
"jobId" : ObjectId("586d7d6acfc7e05669d6e2c8"),
"hourlyRate" : 32
}
{
"_id" : ObjectId("58870cfd59dfb6b0c4eadd72"),
"from" : ISODate("2017-01-28T06:21:00Z"),
"to" : ISODate("2017-01-28T08:21:00Z"),
"jobId" : ObjectId("586d7d6acfc7e05669d6e2c8"),
"hourlyRate" : 32
}
{
"_id" : ObjectId("58870dc659dfb6b0c4eadd73"),
"from" : ISODate("2017-01-29T06:21:00Z"),
"to" : ISODate("2017-01-29T08:21:00Z"),
"jobId" : ObjectId("586d7d6acfc7e05669d6e2c8"),
"hourlyRate" : 32
}
上述聚合查询提供以下输出:
{
"_id" : null,
"jobs" : [
{
"jobId" : ObjectId("586d7d6acfc7e05669d6e2c8"),
"sundayEarnings" : 64,
"saturdayEarnings" : 64,
"weekdayEarnings" : 192,
"totalEarnings" : 320,
"totalWorkedHours" : 10
}
],
"totalJobsEarning" : 320
}
在jobs
数组中只有一个作业,因为shift集合的文档引用了相同的jobId
。您可以使用不同的jobId
来尝试此操作,它会为您提供总收入的不同工作。
答案 1 :(得分:0)
使用 $switch
运算符构建案例陈述的表达式来评估收入,您可以运行以下管道来获得所需的结果
var hoursWorked = {
"$divide": [
{ "$subtract": ["$to", "$from"] },
3600000
]
};
db.collection('shifts').aggregate([
{
"$match": {
"jobId": { "$in": [jobA_id, jobB_id] },
"from": { "$gte": new Date() }
}
},
{
"$group": {
"_id": null,
"totalEarnings": {
"$sum": {
"$switch": {
"branches": [
{
"case": {
"$not": {
"$in": [
{ "$dayOfWeek": "$from" },
[1, 7]
]
}
},
"then": { "$multiply": [hoursWorked, 20] }
},
{
"case": {
"$eq": [
{ "$dayOfWeek": "$from" },
7
]
},
"then": { "$multiply": [hoursWorked, 25] }
},
{
"case": {
"$eq": [
{ "$dayOfWeek": "$from" },
1
]
},
"then": { "$multiply": [hoursWorked, 30] }
}
]
"default": 0
}
}
}
}
}
], function(err, results) {
if (err) throw err;
console.log(JSON.stringify(results, null, 4));
console.log(results[0].totalEarnings);
});