MongoDB:限制来自$pymongo的$gt查询的结果

4 投票
1 回答
3890 浏览
提问于 2025-04-15 19:27

我正在从一个网络服务收集一些统计数据,并把这些数据存储在一个集合里。数据的格式大概是这样的(但字段会更多):

{"downloads": 30, "dt": "2010-02-17T16:56:34.163000"}
{"downloads": 30, "dt": "2010-02-17T17:56:34.163000"}
{"downloads": 30, "dt": "2010-02-17T18:56:34.163000"}
{"downloads": 30, "dt": "2010-02-17T19:56:34.163000"}
{"downloads": 30, "dt": "2010-02-17T20:56:34.163000"}
{…}
{"downloads": 30, "dt": "2010-02-18T17:56:34.163000"}
{"downloads": 30, "dt": "2010-02-18T18:56:34.163000"}
{"downloads": 30, "dt": "2010-02-18T19:56:34.163000"}
{"downloads": 30, "dt": "2010-02-18T20:56:34.163000"}

如果有人请求过去三十天的每日数据,这意味着要获取每天的最大“下载”次数,也就是那一天的最后一条记录。

通过使用 collection.find({"dt": {"$gt": datetime_obj_30_days_ago}}),我当然可以得到所有的记录,但这并不太合适。所以我想找一种方法,只返回在这个时间段内每天的最后一条记录。

有人告诉我可以使用 group(),但我不太明白在这种情况下怎么使用它。

任何建议或指点都非常感谢!

1 个回答

1

你可以使用group这个功能。在你的例子中,你需要提供一个JavaScript函数来计算关键字(还有一个减少函数),因为你只想要日期部分,而不是完整的日期时间字段。这样做应该可以:

db.coll.group(
    key='function(doc) { return {"dt": doc.dt.toDateString()} }',
    condition={'dt': {'$gt': datetime_obj_30_days_ago}},
    initial={'downloads': 0},
    reduce='function(curr, prev) { prev.downloads = Math.max(curr.downloads, prev.downloads) }'
)

要记住的是,这样做仍然会对过去一个月的数据进行线性扫描,只不过是在服务器上进行,而不是在客户端。实际上,单独选择每一天的最大值可能会更快。

撰写回答