mongodb - 如何在 Mongo 中独立地按日期和时间进行过滤?

标签 mongodb mongoose mongodb-query aggregation-framework

如何在 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 operatorsdate operatorsRegular 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/

相关文章:

mongodb - 为什么整数(Number)在MongoDb中保存为Double

mongodb - 嵌入式 MongoDB 尝试下载 Zip

mongodb - 从mongodb中的嵌套数组中只检索匹配的对象

java - Mongodb中的多个$group与java聚合

java - 最佳实践 : Save Empty Fields as null or omit Field Completely and Manage Missing Fields in Code?

Java - Jersey 返回字符串列表

node.js - 使用 mongoose 在 mongodb 中存储图像?如何?

mongoose - Graphql - 获取完整的子对象,如果不存在则返回 null

node.js - 从 Nodejs : [Symbol(mongoErrorContextSymbol)] 与本地 mongodb 连接时出现问题

mongodb - 如何将Mongodb时间点数据分组为连续的时间组?