GroupBy 聚合,包括 mongo 中的缺失日期

Posted

技术标签:

【中文标题】GroupBy 聚合,包括 mongo 中的缺失日期【英文标题】:GroupBy Aggregation including missing dates in mongo 【发布时间】:2021-10-10 15:39:02 【问题描述】:

我有一个聚合查询,当某个日期范围已过时,它会给我一个按日期分组的结果。示例聚合管道如下所示。

[
   $match: 
      orderDate: 
        $gte: new Date('2021-08-01T00:00:00+05:30'),
        $lte: new Date('2021-08-06T23:59:59+05:30'),
      
    ,
  
    $group: 
      _id: 
        $dateToString: 
          format: '%Y-%m-%d',
          date: '$orderDate',
        
      
    
  ]

这会获取类似于下面的结果

[
  
    _id: '2021-08-01',
  ,
  
    _id: '2021-08-02',
  ,
  
    _id: '2021-08-04',
  ,
  
    _id: '2021-08-05',
  ,
]

因此,请注意缺少第 03 天和第 6 天,因为它们不在集合中,但包含在聚合管道中传递的日期范围内。

有没有办法通过调整上述查询来直接查询和获取这些缺失的日期?这将导致正确的值

【问题讨论】:

【参考方案1】:

也许下面的就是你想要的。

1)创建一个带有计数器的集合,例如这里 1-10 10 天

  [
  
    "date": 0
  ,
  
    "date": 1
  ,
  
    "date": 2
  ,
  
    "date": 3
  ,
  
    "date": 4
  ,
  
    "date": 5
  ,
  
    "date": 6
  ,
  
    "date": 7
  ,
  
    "date": 8
  ,
  
    "date": 9
  
  ]
    使用 $add 更新此集合并制作数据,10 个日期 在这里,我们从日期“2021-08-01T00:00:00+00:00”开始,我们将结束 在日期“2021-08-10T00:00:00+00:00”

这个更新会做(q=过滤器,u=更新,这里是它的管道更新)


  "update": "dates",
  "updates": [
    
      "q": ,
      "u": [
        
          "$addFields": 
            "date": 
              "$add": [
                "2021-08-01T00:00:00Z",
                
                  "$multiply": [
                    "$date",
                    24,
                    60,
                    60000
                  ]
                
              ]
            
          
        
      ],
      "multi": true
    
  ]

结果(10 个日期,1 天差)


  "_id": 
    "$oid": "610c4bf99ccb15d9c9d67b55"
  ,
  "date": 
    "$date": "2021-08-01T00:00:00Z"
  
,
  "_id": 
    "$oid": "610c4bf99ccb15d9c9d67b56"
  ,
  "date": 
    "$date": "2021-08-02T00:00:00Z"
  
,
  "_id": 
    "$oid": "610c4bf99ccb15d9c9d67b57"
  ,
  "date": 
    "$date": "2021-08-03T00:00:00Z"
  

...

3) 现在我们有 10 个日期的日期集合,所有日期相差 1 天 我们将使用订单集合进行 $lookup

订单收集

[
  
    "_id": 1,
    "date": "2021-08-01T00:00:00Z"
  ,
  
    "_id": 2,
    "date": "2021-08-01T00:00:00Z"
  ,
  
    "_id": 3,
    "date": "2021-08-05T00:00:00Z"
  ,
  
    "_id": 4,
    "date": "2021-08-03T00:00:00Z"
  
]

查询(取管道,先过滤想要的日期,只有当天下单才加入)


  "aggregate": "dates",
  "pipeline": [
    
      "$match": 
        "$expr": 
          "$and": [
            
              "$gte": [
                "$date",
                
                  "$dateFromString": 
                    "dateString": "2021-08-01T00:00:00"
                  
                
              ]
            ,
            
              "$lte": [
                "$date",
                
                  "$dateFromString": 
                    "dateString": "2021-08-05T00:00:00"
                  
                
              ]
            
          ]
        
      
    ,
    
      "$lookup": 
        "from": "orders",
        "let": 
          "datesDate": "$date"
        ,
        "pipeline": [
          
            "$match": 
              "$expr": 
                "$eq": [
                  
                    "$dateToString": 
                      "format": "%Y-%m-%d",
                      "date": "$$datesDate"
                    
                  ,
                  
                    "$dateToString": 
                      "format": "%Y-%m-%d",
                      "date": "$date"
                    
                  
                ]
              
            
          
        ],
        "as": "found-orders"
      
    ,
    
      "$project": 
        "_id": 0
      
    
  ],
  "cursor": ,
  "maxTimeMS": 1200000

结果

[
  
    "date": "2021-08-01T00:00:00Z",
    "found-orders": [
      
        "_id": 1,
        "date": "2021-08-01T00:00:00Z"
      ,
      
        "_id": 2,
        "date": "2021-08-01T00:00:00Z"
      
    ]
  ,
  
    "date": "2021-08-02T00:00:00Z",
    "found-orders": []
  ,
  
    "date": "2021-08-03T00:00:00Z",
    "found-orders": [
      
        "_id": 4,
        "date": "2021-08-03T00:00:00Z"
      
    ]
  ,
  
    "date": "2021-08-04T00:00:00Z",
    "found-orders": []
  ,
  
    "date": "2021-08-05T00:00:00Z",
    "found-orders": [
      
        "_id": 3,
        "date": "2021-08-05T00:00:00Z"
      
    ]
  
]

这给出了每个日期(每天),当天的订单。 如果某一天没有下订单,则数组为空。 这里只有 10 天,您可以根据自己的需要进行 5 年的日期收集。

【讨论】:

以上是关于GroupBy 聚合,包括 mongo 中的缺失日期的主要内容,如果未能解决你的问题,请参考以下文章

mongodb学习3---mongo的MapReduce

数据分析—Pandas 中的分组聚合Groupby 高阶操作

Pandas groupby 和聚合输出应包括所有原始列(包括未聚合的列)

Python数据聚合和分组运算-GroupBy Mechanics

Mongo高级用法

为啥聚合+排序比mongo中的查找+排序更快?