Mongodb聚合查询$match和$group
Posted
技术标签:
【中文标题】Mongodb聚合查询$match和$group【英文标题】:Mongodb aggregate query $match and $group 【发布时间】:2020-09-22 19:14:33 【问题描述】:以下是我的 mongodb 集合中的一些示例条目:
name: "Tom", timestamp: "Jun 4" ,
name: "Jerry", timestamp: "Jun 4" ,
name: "Tom", timestamp: "Jun 2" ,
name: "Tom", timestamp: "May 25" ,
name: "Jerry", timestamp: "May 21" ,
name: "Robin", timestamp: "May 19"
每次用户登录我的应用时,我都会为该用户创建一个条目。
问题:我需要找出过去 5 天未登录我的应用的用户列表。也就是说,5 月 30 日之后没有条目。今天是 6 月 4 日。
答案: 罗宾
尝试 1:
[
"$match": "timestamp": "$lt": FIVE_DAYS_AGO ,
"$sort": "timestamp": 1 ,
"$group": "_name": "$name", "lastSynced": "$last": "$timestamp"
]
给出不正确的结果,因为在 NOW 和 FIVE_DAYS_AGO 之间可能存在未被考虑的条目。
尝试 2:
[
"$sort": "timestamp": 1 ,
"$group": "_name": "$name", "lastSynced": "$last": "$timestamp"
]
未优化!因为它返回所有不同的用户条目。然后我必须遍历结果并过滤掉时间戳为 FIVE_DAYS_AGO 的条目。
如何构造查询以获取过去 X 天内没有条目的用户列表?
【问题讨论】:
你真的有这样的数据吗 ::timestamp: "Jun 4" 表示它是一个字符串还是timestamp
的数据类型是 date
?
由于您的timestamp
是字符串格式,您需要使用$dateFromString
运算符,如果您查看文档,只有有限的日期字符串,可以转换。因此,我建议您将字段更新为适当的可转换值。
@whoami ,你说得对。它是数据类型date
的timestamp
。为了解释清楚,我把它写成一个字符串。但我想我在这样做的时候把别人弄糊涂了。我的错。
嘿@ngShravil.py,感谢您的解决方案帮助。
【参考方案1】:
注意几点:
请考虑我的评论。
由于您的
timestamp
是字符串格式,您需要使用$dateFromString
运算符,如果您查看文档,只有有限的日期字符串可以转换。因此,我建议您将字段更新为适当的可转换值。
您的$group
不正确。它需要_id
字段,否则会抛出以下错误:
The field '_name' must be an accumulator object.
-
我认为,
timestamp
中需要年份值,我收到此错误:
(ConversionFailure) Error parsing date string
考虑到以上几点,如果您的收藏如下所示:
[
name: "Tom",
timestamp: "06 04 2020"
,
name: "Jerry",
timestamp: "06 04 2020"
,
name: "Tom",
timestamp: "06 02 2020"
,
name: "Tom",
timestamp: "05 25 2020"
,
name: "Jerry",
timestamp: "05 21 2020"
,
name: "Robin",
timestamp: "05 19 2020"
]
那么下面的 PyMongo 查询会有帮助:
from datetime import datetime
five_days_ago = datetime(2020, 5, 30)
db.test12.aggregate([
'$group':
'_id': '$name',
'timestap_list':
'$push':
'$dateFromString':
'dateString': '$timestamp',
'format': '%m %d %Y'
,
'$project':
'timestamp':
'$allElementsTrue':
'$map':
'input': '$timestap_list',
'as': 't',
'in':
'$lte': [
'$$t',
five_days_ago
]
,
'$match':
'timestamp': True
,
'$project':
'timestamp': 0
])
输出:
'_id': 'Robin'
MongoPlayGroundLink
【讨论】:
嘿@ngShravil.py,正如我上面提到的,时间戳字段实际上是数据类型date
,为了便于解释,我将其显示为字符串。我的错。你的解决方案奏效了。然而,我还有另一个问题。如果有第三个字段怎么办。 status
。我只需要选择status: true
所在的行。我通过在$group
之前添加另一个$match
来实现它。有用。但这是正确的方式吗?
是的,没关系。如果这有帮助,那么您可以投票并接受它作为答案。谢谢。以上是关于Mongodb聚合查询$match和$group的主要内容,如果未能解决你的问题,请参考以下文章
MongoDB $geoNear 聚合管道(使用查询选项和使用 $match 管道操作)给出不同的结果
Mongodb聚合$lookup $project和$match不起作用[重复]
Mongodb聚合$lookup $project和$match不起作用[重复]