MongoDB聚合管道:使用For循环

时间:2020-04-15 00:09:54

标签: javascript python mongodb mongodb-query aggregation-framework

我想知道是否有人在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}'
            }
        }
     }
])

}

非常感谢您的帮助:)

1 个答案:

答案 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'}}}
])

Playground

相关问题