【问题标题】:mongodb: query for the time period between two date fieldsmongodb:查询两个日期字段之间的时间段
【发布时间】:2016-07-10 16:03:43
【问题描述】:

如果我的 mongoDB 中保存了以下架构中的文档:

{
  createdDate: Date,
  lastUpdate: Date
}

是否可以查询从创建到最后一次更新之间的时间段的文档,例如超过一天?

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    最好的选择是使用$redact 聚合管道阶段:

    db.collection.aggregate([
        { "$redact": {
            "$cond": {
                "if": {
                    "$gt": [
                        { "$subtract": [ "$lastUpdate", "$createdDate" ] },
                        1000 * 60 * 60 * 24
                    ]
                },
                "then": "$$KEEP",
                "else": "$$PRUNE"
            }
        }}
    ])
    

    因此,您正在查看毫秒值的差异大于一天的毫秒值。 $subtract 计算差异,当减去两个日期时,返回以毫秒为单位的差异。

    $redact 运算符将逻辑表达式作为“if”,在该条件为true 的情况下,它在“then”中执行操作,即对文档$$KEEP。如果是false,那么文档会从带有$$PRUNE 的结果中删除。

    请注意,由于这是一个逻辑条件,而不是设定值或值范围,因此不使用“索引”。

    由于聚合管道中的操作是本机编码的,因此这是您可以获得的最快执行此类语句的方法。

    替代方法是使用 $where 进行 JavaScript 评估。这需要一个 JavaScript 函数表达式,该表达式需要类似地返回 truefalse 值。在 shell 中,你可以这样简写:

    db.collection.find(function() {
        return ( this.lastUpdate.valueOf() - this.createdDate.valueOf() )
           > ( 1000 * 60 * 60 * 24 );
    })
    

    同样的事情,除了 JavaScript 评估需要解释并且运行速度比 .aggregate() 等效的要慢得多。同理,这种类型的表达式不能使用索引来优化性能。

    为了获得最佳结果,请将差异存储在文档中。然后你可以直接查询那个属性,当然你也可以索引它。

    【讨论】:

    • 感谢您的详细解答!作为一个来自 SQL 的人,我没想到它会那么冗长......
    【解决方案2】:

    您可以使用$expr(3.6 mongo 版本运算符)在常规查询中使用聚合函数。

    比较 query operatorsaggregation comparison operators

    db.col.find({$expr:{$gt:[{"$subtract":["$lastUpdate","$createdDate"]},1000*60*60*24]}})
    

    【讨论】:

    • 会比标准聚合查询有更好的性能还是一样?
    【解决方案3】:

    Mongo 5 开始,这是新的$dateDiff 聚合运算符的完美用例:

    // { created: ISODate("2021-12-05T13:20"), lastUpdate: ISODate("2021-12-06T05:00") }
    // { created: ISODate("2021-12-04T09:20"), lastUpdate: ISODate("2021-12-05T18:00") }
    db.collection.aggregate([
      { $match: {
        $expr: {
          $gt: [
            { $dateDiff: { startDate: "$created", endDate: "$lastUpdate", unit: "hour" } },
            24
          ]
        }
      }}
    ])
    // { created: ISODate("2021-12-04T09:20"), lastUpdate: ISODate("2021-12-05T18:00") }
    

    这会计算 createdlastUpdate 日期之间的小时数差异,并检查它是否大于 24 hours。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-08
      • 2017-09-14
      • 2018-05-31
      • 2011-06-12
      • 2013-05-12
      • 2017-01-29
      相关资源
      最近更新 更多