【问题标题】:Date query with ISODate in mongodb doesn't seem to work在 mongodb 中使用 ISODate 进行日期查询似乎不起作用
【发布时间】:2013-11-18 03:35:45
【问题描述】:

我似乎无法让最基本的日期查询在 MongoDB 中工作。使用如下所示的文档:

{
    "_id" : "foobar/201310",
    "ap" : "foobar",
    "dt" : ISODate("2013-10-01T00:00:00.000Z"),
    "tl" : 375439
}

还有一个如下所示的查询:

{ 
    "dt" : { 
        "$gte" : { 
            "$date" : "2013-10-01T00:00:00.000Z"
        }
    }
}

我从执行中得到 0 个结果

db.mycollection.find({
  "dt" : { "$gte" : { "$date" : "2013-10-01T00:00:00.000Z"}}
})

知道为什么这不起作用吗?

作为参考,此查询由 Spring's MongoTemplate 生成,因此我无法直接控制最终发送到 MongoDB 的查询。

(附注)

> db.version()
2.4.7

谢谢!

【问题讨论】:

    标签: json mongodb bson isodate


    【解决方案1】:

    虽然$dateMongoDB Extended JSON 的一部分,而且这是mongoexport 的默认设置,但我认为您不能真正将它用作查询的一部分。

    如果尝试使用$date 进行精确搜索,如下所示:

    db.foo.find({dt: {"$date": "2012-01-01T15:00:00.000Z"}})
    

    你会得到错误:

    error: { "$err" : "invalid operator: $date", "code" : 10068 }
    

    试试这个:

    db.mycollection.find({
        "dt" : {"$gte": new Date("2013-10-01T00:00:00.000Z")}
    })
    

    或者(在@user3805045之后的cmets):

    db.mycollection.find({
        "dt" : {"$gte": ISODate("2013-10-01T00:00:00.000Z")}
    })
    

    ISODate 可能还需要比较没有时间的日期(由@MattMolnar 注明)。

    根据Data Types in the mongo Shell,两者应该是等价的:

    mongo shell 提供了多种方法来返回日期,无论是作为字符串还是作为 Date 对象:

    • Date() 方法以字符串形式返回当前日期。
    • 使用 ISODate() 包装器返回 Date 对象的新 Date() 构造函数。
    • ISODate() 构造函数,它使用 ISODate() 包装器返回一个 Date 对象。

    并使用ISODate should still return a Date object

    {"$date": "ISO-8601 string"} 可以在需要严格的 JSON 表示时使用。一个可能的例子是 Hadoop 连接器。

    【讨论】:

    • 是的。我想当你在 Spring 中打印出 Query 对象时,我被返回的内容吓到了。查询的序列化形式不一定是有效的查询,您可以将其复制/粘贴到 mongo shell 中,这本身就有点令人沮丧。罪魁祸首在这里:grepcode.com/file/repo1.maven.org/maven2/org.mongodb/…
    • 比较部分(无时间)日期时,我不得不从new Date('2016-03-09') 切换到ISODate('2016-03-09')。前者会为 $gte 查询返回过去的日期。
    • @MattMolnar 注意到,并用归属更新了答案。谢谢。
    【解决方案2】:

    来自MongoDB cookbook页面cmets:

    "dt" : 
    {
        "$gte" : ISODate("2014-07-02T00:00:00Z"), 
        "$lt" : ISODate("2014-07-03T00:00:00Z") 
    }
    

    这对我有用。在完整上下文中,以下命令获取 dt 日期字段的日期为 2013-10-01 (YYYY-MM-DD) Zulu 的每条记录:

    db.mycollection.find({ "dt" : { "$gte" : ISODate("2013-10-01T00:00:00Z"), "$lt" : ISODate("2013-10-02T00:00:00Z") }})
    

    【讨论】:

    • 我收到“ISODate undefined”错误。我无法解决这个问题。
    • @BatuhanAkkaya 在带有 pymongo 的 python 中,datetime.datetime 等价于 ISODate
    • @jtbr 不完全是。 ISODate("2014-07-02T00:00:00Z") 的等价物是 datetime.datetime.strptime("2014-07-02T00:00:00Z", "%Y-%m-%dT%H:%M:%SZ").isoformat()
    【解决方案3】:

    试试这个:

    { "dt" : { "$gte" : ISODate("2013-10-01") } }
    

    【讨论】:

      【解决方案4】:

      我使用 robomongo 作为 mongodb 客户端 gui,以下内容对我有用

      db.collectionName.find({"columnWithDateTime" : {
      $lt:new ISODate("2016-02-28T00:00:00.000Z")}})
      

      在应用程序端,我使用的是基于 nodejs 的驱动程序 mongodb(v1.4.3),应用程序在 ui 中使用 datepicker,它给出日期,如 YYYY-mm-dd,然后附加默认时间,如 00:00:00然后给new Date()构造函数,然后提供给mongodb条件对象,我认为驱动程序将日期转换为ISO日期,然后查询工作并给出所需的输出,但是相同的new Date()构造函数不起作用或显示robo mongo 上的相同输出,对于相同的标准,这很奇怪,因为我使用 robomongo 来交叉检查我的标准对象。

      而默认的 cli mongoshell 适用于 ISODatenew Date()

      【讨论】:

      • 感谢您的提示,Robomongo 比 Mongo Compass 好得多
      【解决方案5】:

      在 json 严格模式下,你必须保持顺序:

      {
          "dt": {
              "$gte": {
                  "$date": "2013-10-01T00:00:00.000Z"
              }
          }
      }
      

      唯一能在 mlab.com 上定义我的搜索查询的东西。

      【讨论】:

      • 运行查询时出错。原因:(invalid_operator) 无效的运算符:$date
      【解决方案6】:

      这是我的文件

      "_id" : ObjectId("590173023c488e9a48e903d6"),
          "updatedAt" : ISODate("2017-04-27T04:26:42.709Z"),
          "createdAt" : ISODate("2017-04-27T04:26:42.709Z"),
          "flightId" : "590170f97cb84116075e2680",
      
       "_id" : ObjectId("590173023c488e9a48e903d6"),
              "updatedAt" : ISODate("2017-04-28T03:26:42.609Z"),
              "createdAt" : ISODate("2017-04-28T03:26:42.609Z"),
              "flightId" : "590170f97cb84116075e2680",
      

      现在我想查找每 27 个日期的文档。所以我使用了这个....

       > db.users.find({createdAt:{"$gte":ISODate("2017-04-27T00:00:00Z"),"$lt":ISODate("2017-04-28T00:00:00Z") }}).count()
      
      result:1
      

      这对我有用。

      【讨论】:

        【解决方案7】:

        在 MongoDB 外壳中:

        db.getCollection('sensorevents').find({from:{$gt: new ISODate('2015-08-30 16:50:24.481Z')}})
        

        在我的 nodeJS 代码中(使用 Mongoose)

            SensorEvent.Model.find( {
                from: { $gt: new Date( SensorEventListener.lastSeenSensorFrom ) }
            } )
        

        我正在查询我的传感器事件集合以返回“来自”字段大于给定日期的值

        【讨论】:

        • 欢迎来到 Stack Overflow!请只发布问题的答案,而不是诸如“这是我的第一篇文章”之类的额外内容。将 Stack Overflow 视为 Wikipedia,而不是留言板。
        【解决方案8】:

        new Date()包裹它:

        { "dt" : { "$lt" : new Date("2012-01-01T15:00:00.000Z") } }
        

        【讨论】:

          【解决方案9】:

          老问题,但仍然是第一个谷歌点击,所以我在这里发布,以便我更容易再次找到它......

          使用 Mongo 4.2 和一个聚合():

          db.collection.aggregate(
              [
               { $match: { "end_time": { "$gt": ISODate("2020-01-01T00:00:00.000Z")  } } },
               { $project: {
                    "end_day": { $dateFromParts: { 'year' : {$year:"$end_time"}, 'month' : {$month:"$end_time"}, 'day': {$dayOfMonth:"$end_time"}, 'hour' : 0  } }
               }}, 
               {$group:{
                  _id:   "$end_day",
                  "count":{$sum:1},
              }}
             ]
          )
          

          这个给你 groupby 变量作为日期,有时更好地作为组件本身处理。

          【讨论】:

            【解决方案10】:

            在搜索小于或等于现在的值时,这对我有用:

            db.collectionName.find({ "dt": { "$lte" : new Date() + "" } });
            

            【讨论】:

            • 适用于指南针,但不适用于 Atlas。
            【解决方案11】:

            虽然我针对 AWS DocumentDB(应该与 Mongo 4 兼容)对此进行了测试,但在不使用 DateISODate 的情况下对我来说效果很好:

            db.collection_name.find({"an_iso_date_field": {$lte: "2021-02-04T03:42:00Z"}})
            

            【讨论】:

              猜你喜欢
              • 2020-11-28
              • 1970-01-01
              • 1970-01-01
              • 2017-01-15
              • 1970-01-01
              • 1970-01-01
              • 2020-03-06
              • 1970-01-01
              相关资源
              最近更新 更多