MongoDB 多层次分组
MongoDB Group on Multiple Levels
我有一组事件数据,我想对其执行 aggregate/grouping 以将事件数据汇总为一个结果。我遇到的问题是如何按照我想要的方式组织数据 return 结果。
示例数据:
db.events.find({})
{
eventId : "abc",
eventDate : 1420088400000,
eventLength : 1800000,
eventStart : 59100000,
attendees : [
"userA",
"userB",
"userC"
],
otherData : "...",
etc : "..."
},{
eventId : "def",
eventDate : 1421557200000,
eventLength : 3600000,
eventStart : 36000000,
attendees : [
"userA",
"userG",
"userZ"
],
otherData : "...",
etc : "..."
},{
eventId : "ghi",
eventDate : 1420088400000,
eventLength : 7200000,
eventStart : 45000000,
attendees : [
"userD",
"userE",
"userA"
],
otherData : "...",
etc : "..."
}
基本上日期's/time's/and 长度都存储为表示毫秒的 long 或 int,因此添加 eventDate + eventStart 将为您提供 UTC 日期和开始时间。添加 eventDate + eventStart + eventLength 将为您提供 UTC 的事件结束时间。
我想做的是创建和聚合,使我能够 $match 与会者中的 userId(这里没有概率),但按 day/week/month/year/overall.[=13 显示一组数据=]
因此示例结果将是示例(这对上面示例数据中的时间不准确,但正在寻找如何编写此分组的脚本..)
{
userId : "userA",
req : 75.0,
totals : [
{
period : "day",
events : 2, //this means two event for today
eventsLength : 7200000, //$sum of the 2 events length
},{
period : "week",
events : 3, //this means 3 events in the week
eventsLength : 9600000, //$sum of the 3 events length
},{
period : "month",
events : 8, //this means 8 events in the month
eventsLength : 15000000, //$sum of the 8 events length
},{
period : "year",
events : 15, //this means 15 events in the year
eventsLength : 15000000, //$sum of the 15 events length
},{
period : "overall",
events : 23, //this means 23 events lifetime
eventsLength : 72000000, //$sum of the 23 events length
}
]
}
因此,对于每个 "period",我基本上想保留一个 运行 总数,并对 eventLength 和事件数求和。 "req" 表示给定当前日期,用户已完成 3/4 事件 (75%)。它独立于总数,基本上它只是一个百分比,表示目标是每周 4 场比赛,这是你完成的百分比。所以你看在 "week" 期间,他们只有 4 个中的 3 个作为目标。
总的来说,我已经尝试了 $match、$project 和 $group 的组合来尝试生成此输出,但我希望有人可以帮助分组 运行 总数。 .
我已经为给定当前日期的每个时间段计算出 date/milliseconds,所以我已经将其预先确定为变量,我只是不知道如何构建 aggregate/grouping 来生成这个结果..
感谢任何帮助!
在昨天弄乱之后,我得到了这个解决方案,它不是我正在寻找的确切输出,我将总计作为一个数组,每个 "period" 或数组元素作为一个集合总计的总和,但是这会输出一个集合,按 "period (day/week/month/year/overall)" 分段,每个集合的总计..
{
$match: {userId : "ABC123"}
},{
$project : {
_id : 0,
d : {$cond:{if:{$and:[{$gte:["$eventDate", "${dayStart}"]},{$lte:["$eventDate", "${dayEnd}"]}]},
then: {d : "$eventLength", c : {"$literal" : 1}},
else: null }
},
w : {$cond:{if:{$and:[{$gte:["$eventDate","${weekStart}"]},{$lte:["$eventDate", "${weekEnd}"]}]},
then: {d : "$eventLength", c : {"$literal" : 1}},
else: null }
},
m : {$cond:{if:{$and:[{$gte:["$eventDate","${monthStart}"]},{$lte:["$eventDate","${monthEnd}"]}]},
then: {d : "$eventLength", c : {"$literal" : 1}},
else: null }
},
y : {$cond:{if:{$and:[{$gte:["$eventDate","${yearStart}"]},{$lte:["$eventDate","${yearEnd}"]}]},
then: {d : "$eventLength", c : {"$literal" : 1}},
else: null }
},
o : {$cond:{if:{$lte:["$eventDate","${yearEnd}"]},
then: {d : "$eventLength", c : {"$literal" : 1}},
else: null }
}
}
},{
$group : {
_id : null,
day_d : {$sum : "$d.d"},
day_c : {$sum : "$d.c"},
week_d : {$sum : "$w.d"},
week_c : {$sum : "$w.c"},
month_d : {$sum : "$m.d"},
month_c : {$sum : "$m.c"},
year_d : {$sum : "$y.d"},
year_c : {$sum : "$y.c"},
over_d : {$sum : "$o.d"},
over_c : {$sum : "$o.c"}
}
},{
$project : {
_id : 0,
day : {events : "$day_c", millisTotal : "$day_d"},
week : {events : "$week_c", millisTotal : "$week_d"},
month : {events : "$month_c", millisTotal : "$month_d"},
year : {events : "$year_c", millisTotal : "$year_d"},
overall : {events : "$over_c", millisTotal : "$over_d"},
req : {
$cond : {
if : { $gte : ["$week_c", 4]}, then : 100,
else : {
$cond : {
if : { $eq : ["$week_c", 3] }, then : 75,
else : {
$cond : {
if : { $eq : ["$week_c", 2] }, then : 50,
else : {
$cond : {
if : { $eq : ["$week_c", 1] }, then : 25,
else : 0
}
}
}
}
}
}
}
}
}
}
这会生成如下所示的输出..
{
day : {
events : 1,
millisTotal : 7200000
},
week : {
events : 2,
millisTotal : 14400000
},
month : {
events : 17,
millisTotal : 87345000
},
year : {
events : 17,
millisTotal : 87345000
},
overall : {
events : 18,
millisTotal : 92745000
},
req : 50
}
我注意到的一件事是它几乎不可能将 $project 返回到数组元素中,这样我就可以将每个周期集合作为数组元素的 "totals : []",但是现在这是可行的..如果任何人有反馈或更好的方法来完成这个,我会把它打开一点,看看是否有更好的答案出现..我喜欢这个作为总计数组的原因是使用这个输出的逻辑可以更动态,而不是期望一组特定的 "keys" 作为 day/week/month/year/overall.
我有一组事件数据,我想对其执行 aggregate/grouping 以将事件数据汇总为一个结果。我遇到的问题是如何按照我想要的方式组织数据 return 结果。
示例数据:
db.events.find({})
{
eventId : "abc",
eventDate : 1420088400000,
eventLength : 1800000,
eventStart : 59100000,
attendees : [
"userA",
"userB",
"userC"
],
otherData : "...",
etc : "..."
},{
eventId : "def",
eventDate : 1421557200000,
eventLength : 3600000,
eventStart : 36000000,
attendees : [
"userA",
"userG",
"userZ"
],
otherData : "...",
etc : "..."
},{
eventId : "ghi",
eventDate : 1420088400000,
eventLength : 7200000,
eventStart : 45000000,
attendees : [
"userD",
"userE",
"userA"
],
otherData : "...",
etc : "..."
}
基本上日期's/time's/and 长度都存储为表示毫秒的 long 或 int,因此添加 eventDate + eventStart 将为您提供 UTC 日期和开始时间。添加 eventDate + eventStart + eventLength 将为您提供 UTC 的事件结束时间。
我想做的是创建和聚合,使我能够 $match 与会者中的 userId(这里没有概率),但按 day/week/month/year/overall.[=13 显示一组数据=]
因此示例结果将是示例(这对上面示例数据中的时间不准确,但正在寻找如何编写此分组的脚本..)
{
userId : "userA",
req : 75.0,
totals : [
{
period : "day",
events : 2, //this means two event for today
eventsLength : 7200000, //$sum of the 2 events length
},{
period : "week",
events : 3, //this means 3 events in the week
eventsLength : 9600000, //$sum of the 3 events length
},{
period : "month",
events : 8, //this means 8 events in the month
eventsLength : 15000000, //$sum of the 8 events length
},{
period : "year",
events : 15, //this means 15 events in the year
eventsLength : 15000000, //$sum of the 15 events length
},{
period : "overall",
events : 23, //this means 23 events lifetime
eventsLength : 72000000, //$sum of the 23 events length
}
]
}
因此,对于每个 "period",我基本上想保留一个 运行 总数,并对 eventLength 和事件数求和。 "req" 表示给定当前日期,用户已完成 3/4 事件 (75%)。它独立于总数,基本上它只是一个百分比,表示目标是每周 4 场比赛,这是你完成的百分比。所以你看在 "week" 期间,他们只有 4 个中的 3 个作为目标。
总的来说,我已经尝试了 $match、$project 和 $group 的组合来尝试生成此输出,但我希望有人可以帮助分组 运行 总数。 .
我已经为给定当前日期的每个时间段计算出 date/milliseconds,所以我已经将其预先确定为变量,我只是不知道如何构建 aggregate/grouping 来生成这个结果..
感谢任何帮助!
在昨天弄乱之后,我得到了这个解决方案,它不是我正在寻找的确切输出,我将总计作为一个数组,每个 "period" 或数组元素作为一个集合总计的总和,但是这会输出一个集合,按 "period (day/week/month/year/overall)" 分段,每个集合的总计..
{
$match: {userId : "ABC123"}
},{
$project : {
_id : 0,
d : {$cond:{if:{$and:[{$gte:["$eventDate", "${dayStart}"]},{$lte:["$eventDate", "${dayEnd}"]}]},
then: {d : "$eventLength", c : {"$literal" : 1}},
else: null }
},
w : {$cond:{if:{$and:[{$gte:["$eventDate","${weekStart}"]},{$lte:["$eventDate", "${weekEnd}"]}]},
then: {d : "$eventLength", c : {"$literal" : 1}},
else: null }
},
m : {$cond:{if:{$and:[{$gte:["$eventDate","${monthStart}"]},{$lte:["$eventDate","${monthEnd}"]}]},
then: {d : "$eventLength", c : {"$literal" : 1}},
else: null }
},
y : {$cond:{if:{$and:[{$gte:["$eventDate","${yearStart}"]},{$lte:["$eventDate","${yearEnd}"]}]},
then: {d : "$eventLength", c : {"$literal" : 1}},
else: null }
},
o : {$cond:{if:{$lte:["$eventDate","${yearEnd}"]},
then: {d : "$eventLength", c : {"$literal" : 1}},
else: null }
}
}
},{
$group : {
_id : null,
day_d : {$sum : "$d.d"},
day_c : {$sum : "$d.c"},
week_d : {$sum : "$w.d"},
week_c : {$sum : "$w.c"},
month_d : {$sum : "$m.d"},
month_c : {$sum : "$m.c"},
year_d : {$sum : "$y.d"},
year_c : {$sum : "$y.c"},
over_d : {$sum : "$o.d"},
over_c : {$sum : "$o.c"}
}
},{
$project : {
_id : 0,
day : {events : "$day_c", millisTotal : "$day_d"},
week : {events : "$week_c", millisTotal : "$week_d"},
month : {events : "$month_c", millisTotal : "$month_d"},
year : {events : "$year_c", millisTotal : "$year_d"},
overall : {events : "$over_c", millisTotal : "$over_d"},
req : {
$cond : {
if : { $gte : ["$week_c", 4]}, then : 100,
else : {
$cond : {
if : { $eq : ["$week_c", 3] }, then : 75,
else : {
$cond : {
if : { $eq : ["$week_c", 2] }, then : 50,
else : {
$cond : {
if : { $eq : ["$week_c", 1] }, then : 25,
else : 0
}
}
}
}
}
}
}
}
}
}
这会生成如下所示的输出..
{
day : {
events : 1,
millisTotal : 7200000
},
week : {
events : 2,
millisTotal : 14400000
},
month : {
events : 17,
millisTotal : 87345000
},
year : {
events : 17,
millisTotal : 87345000
},
overall : {
events : 18,
millisTotal : 92745000
},
req : 50
}
我注意到的一件事是它几乎不可能将 $project 返回到数组元素中,这样我就可以将每个周期集合作为数组元素的 "totals : []",但是现在这是可行的..如果任何人有反馈或更好的方法来完成这个,我会把它打开一点,看看是否有更好的答案出现..我喜欢这个作为总计数组的原因是使用这个输出的逻辑可以更动态,而不是期望一组特定的 "keys" 作为 day/week/month/year/overall.