【问题标题】:Project entire document from mongo by max created date time按最大创建日期时间从 mongo 投影整个文档
【发布时间】:2020-05-17 18:45:03
【问题描述】:

我创建了这个查询来获取某个日期时间范围内的所有文档的最大创建日期时间。我正在查找每小时所有最新文档的列表。

pipe = [
  {
    "$addFields": {
      "start": {
        "$dateFromString": {
          "dateString": "$StartTime",
          "format": "%Y-%m-%dT%H:%M:%S%z"
        }
      },
      "created": {
        "$dateFromString": {
          "dateString": "$CreatedDateTime",
          "format": "%Y-%m-%dT%H:%M:%S%z"
        }
      }
    }
  },
  {
    "$match": {
      "start": {
        "$gte": start_time,
        "$lte": end_time
      }
    }
  },
  {
    "$sort": {
      "created": -1
    }
  },
  {
    "$group": {
      "_id": "$start",
      "doc": {
        "$first": "$$ROOT"
      }
    }
  },
  {
    "$replaceRoot": {
      "newRoot": "$doc"
    }
  }
]
cursor = COLLECTION.aggregate(pipeline=pipe)

但是,由于我使用的是 $addFields,所以我也在投射 startcreated,这不是我在寻找的。我能否以排除这些字段并仅包含原始文档的方式复制此查询。我还想知道这是否不是我的解决方案的最佳查询,因此欢迎任何输入或建议。

这是一个示例文档:

{
  "StartTime" : "2020-05-01T00:00:00-05:00",
  "EndTime" : "2020-05-01T00:59:59-05:00",
  "Value" : 100,
  "CreatedDateTime" : "2020-05-01T00:00:00-05:00"
}

如果我要查询一小时,这就是查询返回的内容:

{
  "StartTime" : "2020-05-01T00:00:00-05:00",
  "EndTime" : "2020-05-01T00:59:59-05:00",
  "Value" : 100,
  "CreatedDateTime" : "2020-05-01T00:00:00-05:00",
  "start" : datetime.datetime(2020,05,01),
  "created" : datetime.datetime(2020,05,01)
}

如果我要查询多个小时,我正在寻找的结果是示例文档或示例文档列表。

【问题讨论】:

  • 请使用示例文档和所需的 o/p 编辑此帖子。

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


【解决方案1】:

聚合管道中不需要$addFields 阶段。只需将start_timeend_time 转换为字符串。将start 替换为StartTime,将created 替换为CreatedDateTime

所以,最后你的查询应该如下所示:

pipe = [{
  "$match": {
    "StartTime": {
      "$gte": start_time,
      "$lte": end_time
    }
  }
},
{
  "$sort": {
    "CreatedDateTime": -1
  }
},
{
  "$group": {
    "_id": "$StartTime",
    "doc": {
      "$first": "$$ROOT"
    }
  }
},
{
  "$replaceRoot": {
    "newRoot": "$doc"
  }
}]
cursor = COLLECTION.aggregate(pipeline=pipe)

就我而言,我初始化了start_timeend_time,如下所示:

from datetime import datetime
start_time = datetime.strptime('01 May 2020 00:00:00-05:00', '%d %b %Y %H:%M:%S%z').strftime('%Y-%m-%dT%H:%M:%S%z') # Value: 2020-05-01T00:00:00-05:00
start_time = start_time[:-2]+':'+start_time[-2:]
end_time = datetime.strptime('01 May 2020 00:59:59-05:00', '%d %b %Y %H:%M:%S%z').strftime('%Y-%m-%dT%H:%M:%S%z') # Value: 2020-05-01T00:59:59-05:00
end_time = end_time[:-2]+':'+end_time[-2:]

你可以像上面那样做一些修改,然后运行查询。

简短说明: 字符串比较以字典顺序进行。所以,"01" 小于"02""03" 大于"01",同样,"2020-05-01 00:00:00-05:00" 小于等于"2020-05-01T00:00:00-05:00""2020-05-01 00:59:59-05:00" 大于等于"2020-05-01T00:00:00-05:00"

希望以上内容有所帮助。

【讨论】:

  • 感谢您的回复。我已经尝试过这个解决方案,但我不相信它是按时间比较的。当我输入两个不同的日期时,我得到了响应,但是当我输入同一天的不同时间时,它无法返回任何文件。我不认为它是在小时/分钟/秒级别进行比较,而只是在年/月/日进行比较。
  • 你能提供那个测试用例吗,我可以改进它吗?
  • 对于您在答案中的相同 start_time 和 end_time ,它不会返回任何值。如果我将 end_time 更改为 5 月 2 日,它将返回 5 月 1 日的所有时间。我不确定是什么导致了这个问题,因为逻辑看起来很合理。必须是比较字符串日期的东西。
  • 您能否确保,两个日期都以相同的格式提供:'%d %b %Y %H:%M:%S%z
  • 是的,我将 start_time 和 end_time 初始化为您的答案,在调试器中我可以看到 start_time 为 '2020-02-07 00:00:00-05:00' 和 end_time 为 '2020- 02-07 00:59:59-05:00' 被传递给查询(我使用 mongo 中的日期作为示例),结果是一个空列表 []。但是,将 end_time 更改为 2020-02-08 会返回 2020-02-07 的所有时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-16
  • 1970-01-01
相关资源
最近更新 更多