mongodb:查询两个日期字段之间的时间段

zap*_*984 4 mongodb mongodb-query aggregation-framework

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

{
  createdDate: Date,
  lastUpdate: Date
}
Run Code Online (Sandbox Code Playgroud)

是否可以查询创建和上次更新之间的时间段是否大于一天的文档?

Bla*_*ven 7

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

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

因此,您正在查看差值的毫秒值,该值大于一天的毫秒值.在$subtract做数学的区别,当两个日期相减返回以毫秒为单位的差异.

$redact操作者取逻辑表达式为"如果",且其中该条件是true它要执行的操作在"然后",这是到$$KEEP该文档.如果是,false那么文档将从结果中删除$$PRUNE.

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

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

替代是JavaScript评估$where.这需要一个JavaScript函数表达式,需要类似地返回一个truefalse值.在shell中你可以像这样简写:

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

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

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


Xav*_*hot 4

从 开始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") }
Run Code Online (Sandbox Code Playgroud)

created这会计算和日期之间相差的小时数lastUpdate,并检查是否大于24 hours。