【问题标题】:Getting last entry of the months from mongo collection从 mongo 集合中获取月份的最后一个条目
【发布时间】:2021-03-17 02:13:21
【问题描述】:

按以下格式说出集合存储数据。每天都会在集合中添加一个新条目。日期采用 ISO 格式。

|id|dt|data|
---
|1|2021-03-17|{key:"A", value:"B"}
...
|1|2021-03-14|{key:"A", value:"B"}
...
|1|2021-02-28|{key:"A", value:"B"}
|1|2021-02-27|{key:"A", value:"B"}
...
|1|2021-02-01|{key:"A", value:"B"}
|1|2021-01-31|{key:"A", value:"B"}
|1|2021-01-30|{key:"A", value:"B"}
...
|1|2021-01-01|{key:"A", value:"B"}
|1|2020-12-31|{key:"A", value:"B"}
...
|1|2020-11-30|{key:"A", value:"B"}
...

我需要一个查询方面的帮助,该查询提供给定时间段内每个月的最后一天。以下是我能够执行的查询,它没有给出当月的最后一天,因为我按日、月和年对其进行排序。

db.getCollection('data').aggregate([
    {
      $match: {dt: {$gt: ISODate("2020-01-01")}
    },
    {
      $project: {
        dt: "$dt",
        month: {
          $month: "$dt"
        },
        day: {
          $dayOfMonth: "$dt"
        },
        year: {
          $year: "$dt"
        },
        data: "$data"
      }
    },
    {
        $sort: {day: -1, month: -1, year: -1}
    },
    { $limit: 24},
    {
        $sort: {dt: -1}
    },
])

我追求的结果是:

|1|2021-03-17|{key:"A", value:"B"}
|1|2021-02-28|{key:"A", value:"B"}
|1|2021-01-31|{key:"A", value:"B"}
|1|2020-12-31|{key:"A", value:"B"}
|1|2020-11-30|{key:"A", value:"B"}
...
|1|2020-01-31|{key:"A", value:"B"}

【问题讨论】:

  • 你能用日期时间对象查询iso格式吗?如果是这样,这可能是一个 or 查询,每个查询都是 $gte 该月的最后一天和 $lt 该月的第一天。
  • 我更新了我的问题。我需要集合中本月的最后一个条目。
  • 你需要数据库中每个月的最后一条记录,还是每个月最后一天的数据?

标签: mongodb aggregate


【解决方案1】:

按年和月对记录进行分组,得到该月的最大日期。

db.getCollection('data').aggregate([
    { $match: { dt: { $gt: ISODate("2020-01-01") } } },
    { $group: { // group by
      _id: { $substr: ['$dt', 0, 7] }, // get year and month eg 2020-01
      dt: { $max: "$dt" }, // find the max date
      doc:{ "$first" : "$$ROOT" } } // to get the document
    },
    { "$replaceRoot": { "newRoot": "$doc"} }, // project the document
    { $sort: { dt: -1 } }
]);

$substr

$group

$replaceRoot

$max

$first

【讨论】:

    【解决方案2】:

    我在 Python 中为您修补了一个可能的解决方案,但是如果没有您的数据库,我不能肯定它是否有效。

    首先有一个函数接受一个表示月份的整数并返回该月的最后一天。

    import datetime as dt
    
    
    def last_day_of_month(month):
    
        return dt.datetime(2021, month+1, 1) - dt.timedelta(days=1)
    

    接下来,我使用单独的函数构建了查询。

    def build_query(last_month):
    
        return [
        {
            "$and": [
                {"date": {"$gte": last_day_of_month(i)}},
                {"date": {"$lt": last_day_of_month(i) + dt.timedelta(days=1)}}
            ]
        }
        for i in range(0, last_month)
    ]
    

    这是输出。它将位于$match 阶段的$or 运算符内。

        {'$match': {'$or': [{'$and': [{'date': {'$gte': datetime.datetime(2020, 12, 31, 0, 0)}},
         {'date': {'$lt': datetime.datetime(2021, 1, 1, 0, 0)}}]},
       {'$and': [{'date': {'$gte': datetime.datetime(2021, 1, 31, 0, 0)}},
         {'date': {'$lt': datetime.datetime(2021, 2, 1, 0, 0)}}]},
       {'$and': [{'date': {'$gte': datetime.datetime(2021, 2, 28, 0, 0)}},
         {'date': {'$lt': datetime.datetime(2021, 3, 1, 0, 0)}}]},
       {'$and': [{'date': {'$gte': datetime.datetime(2021, 3, 31, 0, 0)}},
         {'date': {'$lt': datetime.datetime(2021, 4, 1, 0, 0)}}]},
       {'$and': [{'date': {'$gte': datetime.datetime(2021, 4, 30, 0, 0)}},
         {'date': {'$lt': datetime.datetime(2021, 5, 1, 0, 0)}}]},
       {'$and': [{'date': {'$gte': datetime.datetime(2021, 5, 31, 0, 0)}},
         {'date': {'$lt': datetime.datetime(2021, 6, 1, 0, 0)}}]},
       {'$and': [{'date': {'$gte': datetime.datetime(2021, 6, 30, 0, 0)}},
         {'date': {'$lt': datetime.datetime(2021, 7, 1, 0, 0)}}]},
       {'$and': [{'date': {'$gte': datetime.datetime(2021, 7, 31, 0, 0)}},
         {'date': {'$lt': datetime.datetime(2021, 8, 1, 0, 0)}}]},
       {'$and': [{'date': {'$gte': datetime.datetime(2021, 8, 31, 0, 0)}},
         {'date': {'$lt': datetime.datetime(2021, 9, 1, 0, 0)}}]},
       {'$and': [{'date': {'$gte': datetime.datetime(2021, 9, 30, 0, 0)}},
         {'date': {'$lt': datetime.datetime(2021, 10, 1, 0, 0)}}]},
       {'$and': [{'date': {'$gte': datetime.datetime(2021, 10, 31, 0, 0)}},
         {'date': {'$lt': datetime.datetime(2021, 11, 1, 0, 0)}}]},
       {'$and': [{'date': {'$gte': datetime.datetime(2021, 11, 30, 0, 0)}},
         {'date': {'$lt': datetime.datetime(2021, 12, 1, 0, 0)}}]}]}}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-23
      • 2021-12-09
      • 2022-10-19
      • 1970-01-01
      • 2019-03-02
      • 2014-05-12
      相关资源
      最近更新 更多