如何在 Mongo 中独立地按日期和时间进行过滤?
我希望能够在数据库中独立保存日期和日期,在数据库中我可以独立地按日期和时间进行过滤。
我应该只有一个字段来保存日期对象吗?如果是的话我怎样才能按时间过滤。我怎样才能获得有关记录的统计信息,例如日期从 01/05/2017 到 15/03/2018 AND 记录的时间应该在下午 3 点到 5 点之间(所以一条记录日期为 12/03/2018 且时间为下午 5:05 的内容不应包含在内)。
最佳答案
这里要考虑的重要一点是,您实际上需要继续使用 "regular query operators"在这里,否则你的性能将会大幅下降。这个想法是始终编写一个实际上可以“使用索引”的查询,然后确保索引存在。
因此,“天”的选择是一个标准范围查询,其余部分仅回退到通过“计算”过滤表达式,并考虑到“已选择”的文档,通过正确指定标准查询条件优先:
MongoDB 3.6 - $expr
db.collection.find({
"date": { "$gte": new Date("2017-05-01"), "$lt": new Date("2018-03-16") },
"$expr": {
"$and": [
{ "$gte": [{ "$hour": "$date" }, 15 ] },
{ "$lt": [{ "$hour": "$date", 17 ] }
]
}
})
使用$expr
用于评估聚合框架的查询运算符logical operators和 date operators 。 Regular comparison operators用于日期范围表达式。
较低版本 - Aggregate 和 $redact
db.collection.aggregate([
{ "$match": {
"date": { "$gte": new Date("2017-05-01"), "$lt": new Date("2018-03-16") }
}},
{ "$redact": {
"$cond": {
"if": {
"$and": [
{ "$gte": [{ "$hour": "$date" }, 15 ] },
{ "$lt": [{ "$hour": "$date", 17 ] }
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
相同的聚合表达式,但使用 $redact
应用管道阶段。相同Regular comparison operators对于 $match
的日期范围表达式.
所有版本 - $where
var startHour = 15,
endHour = 17;
db.collection.find({
"date": { "$gte": new Date("2017-05-01"), "$lte": new Date("2018-03-15") },
"$where": `this.data.getUTCHours() => ${startHour}
&& this.data.getUTCHours() < ${endHour}`
})
使用 JavaScript 评估 $where
。除非明确禁用服务器端脚本,否则在所有版本中均可用。注意“相同”和Regular comparison operators用于主要选择日期范围。
在所有情况下,必须表达“标准查询运算符”条件“第一个”。如果没有这个,MongoDB 就无法使用数据上存在的索引,并且需要扫描集合中的每个文档以计算条件并查看是否返回文档。
使用 $gte
添加“标准运算符”条件和 $lt
range 确保可以使用索引,而剩余的“计算”逻辑表达式仅实际应用于那些已经满足“第一个”条件的文档。
对于“奖励”,您甚至可以将时间限制放在“天”本身上,因此您甚至不需要分别考虑开始日和结束日的下午 3 点之前或下午 5 点之后的时间:
"date": { "$gte": new Date("2017-05-01T15:00"), "$lt": new Date("2018-03-16T17:00") }
所以只要有可能,总是"use an index"并确保您的查询表达式实际上是为了使用它们而构建的,而不是其他形式。
NOTE The general logic here is that "performance" of all presented solutions here should scale in the order of presentation, being
$expr
best to$where
worst. At present writing however, there appears to be a regression in the MongoDB 3.6 release where in fact the$where
typically performs better that it's counterparts actually using native operators.This should not be the "ongoing" case however and should get resolved, so it is generally recommended you use the native operator compositions as opposed to JavaScript logic with
$where
.
关于mongodb - 如何在 Mongo 中独立地按日期和时间进行过滤?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50118434/