在Mongo中进行GroupBy聚合时包括缺失的日期

3

当传递一个日期范围时,我有一个聚合查询可以按日期分组给出结果。示例的聚合管道大致如下。

[{
   $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和06已经丢失,但是它们包含在传递给聚合管道的日期范围内。

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

1个回答

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
  }
  ]
  1. 更新此集合并使用$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年的日期集合。


请问您能否创建一个Playground?我也有类似的需求。我的帖子 @Takis - Pallab

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接