我想知道是否有人在MongoDB中有更好的查询方式。
我有一个集合,其中存储有一个用户ID的每小时信息。该集合将为每个文档提供唯一的user_id和日期组合。但是user_id可以具有多个具有不同日期的整体。下面提供了示例文档条目
{ user_id : A,
date. : '2020-04-01'
hourly_info :
{ metric_one :
{ 0 : 4,
1: 7,
2:8
..
23: 43 }}}
我的问题是:对于给定的user_id和daterange,按user_id分组,并计算每小时的metric_one之和。示例输出如下所示
{“ _id”:“ A”,“ 0”:45,“ 1”:28,“ 2”:31,....“ 23”:67}。
我的查询:
db.collection.aggregate([
{ '$match': {
'user_id':"A",
'date':{'$lte':ISODate('2020-04-01'),
'$gte':ISODate('2020-04-08') }
} },
{'$group':{
_id: '$user_id',
'0': { '$sum': '$hourly_info.metric_one.0'},
'1': { '$sum': '$hourly_info.metric_one.1'},
... ,
'23':{ '$sum': '$hourly_info.metric_one.23'}
}}
]).pretty()
如果有人能说除了从0到23的每个小时的求和以外,还有什么更好的查询方法,我将不胜感激。
有没有更好的方法可以利用for循环,这样我就不会为0到23编写相同的求和逻辑?
类似
for (i = 0; i <= 23; i=i+1){
db.collection.aggregate([{
'$match': {
'user_id':"A",
'sales_date':{
'$lte':ISODate('2020-04-01'),
'$gte':ISODate('2020-04-08')
}
}
}, {
'$group': {
'_id': '$user_id',
{i}: {
'$sum': '$hourly_info.metric_one.{i}'
}
}
}
])
}
非常感谢您的帮助:)
答案 0 :(得分:1)
这可以通过聚合来完成。您可以使用$ objectToArray并展开以将每小时的数据拆分为单独的文档,然后进行两次分组-一次进行每小时计数,一次进行一次收集以供用户使用。然后$ arrayToObject使其再次成为对象。
db.collection.aggregate([
{'$match': {
'user_id':"A",
'date':{'$gte':ISODate('2020-04-01'),
'$lte':ISODate('2020-04-08')}
}},
{'$addFields':{
'hourly_info.metric_one': {$objectToArray: '$hourly_info.metric_one'}
}},
{'$unwind':'$hourly_info.metric_one'},
{'$group':{
_id: {
'user':'$user_id',
'hour':'$hourly_info.metric_one.k'
},
'total': { '$sum': '$hourly_info.metric_one.v'}
}},
{'$group':{
'_id':'$_id.user',
'hourly':{'$push':{'k':'$_id.hour','v':'$total'}}
}},
{'$addFields': {'hourly':{'$arrayToObject':'$hourly'}}}
])