【问题标题】:Gmongo date queryGmongo日期查询
【发布时间】:2014-03-28 10:59:51
【问题描述】:

给定一个 mongo 集合(为了说明目的,仅精简到几个字段):

{
    "_id" : ObjectId("52402905e4b0cebf1e474093"),
    "impressionId" : LUUID("6a46028f-aa02-e87d-c097-01df765ec487"),
    "requestTime" : ISODate("2013-09-23T11:41:57.505Z"),
    "responseTime" : ISODate("2013-09-23T11:41:57.712Z"),
}

我想查询 requestTime。理想情况下,我想要两个查询,一个用于确切的 requestTime,一个用于一系列 requestTimes(大于或等于某个日期时间,小于或等于某个其他日期时间)。到目前为止,我已经尝试了以下方法,但似乎都没有:

def fromDate = new Date(2013, 9, 22, 11, 41, 57)
def fromDateLong = fromDate.getTime()
def toDate = new Date(2013, 9, 23, 11, 41, 58);
def toDateLong = toDate.getTime()

// None of these return a record
def result = db.activityLog.find(requestTime : ['$date' : '2013-09-23T11:41:57.505Z']).count()
def result = db.activityLog.find(requestTime : ['$gte' : fromDateLong, '$lte' : toDateLong]).count()
def result = db.activityLog.find(requestTime : ["\\\$gte" : fromDateLong, "\\\$lte" : toDateLong]).count()
def result = db.activityLog.find(requestTime : ['$gte' : fromDate, '$lte' : toDate]).count()
def result = db.activityLog.find(requestTime : ["\\\$gte" : fromDate, "\\\$lte" : toDate]).count()

// I have also tried to read the first record form the mongo collection pull out the date (which works fine) and then query for this date (which doesn't work):

def result = db.activityLog.findOne()
println result.requestTime  // prints correct requestTime
def requestTimeLong = result.requestTime.getTime()
println requestTimeLong  // prints correct requestTime

def result2 = db.activityLog.find(requestTime : ["\\\$gte" : requestTimeLong]).count()
def result3 = db.activityLog.find(requestTime : ["\\\$date" : requestTimeLong]).count()
def result4 = db.activityLog.find(requestTime : ["\\\$gte" : result.requestTime]).count()
def result5 = db.activityLog.find(requestTime : ["\\\$date" : result.requestTime]).count()

println result2 // prints 0 for both above queries i.e. no records found
println result3 // prints 0 for both above queries i.e. no records found
println result4 // prints 0 for both above queries i.e. no records found
println result5 // prints 0 for both above queries i.e. no records found

有人有什么建议吗?对此的任何帮助将不胜感激。

我已经取得了一些进展,但还没有完全奏效。我可以检索记录并提取日期并在有效的查询中使用该日期。但是,如果我尝试自己创建日期,它将不起作用:

def result = db.activityLog.findOne(impressionId : ['$exists' : true])
def requestTimeResult = result.requestTime
println requestTimeResult
println requestTimeResult.class
def requestTimeLong = result.requestTime.getTime()
println requestTimeLong

def result2 = db.activityLog.find(requestTime: ['$gte': ['$date' : requestTimeLong]]).count()
def result3 = db.activityLog.find(requestTime: ['$gte': requestTimeResult]).count()

println result2
println result3

def fromDateNew = new Date(2013, 8, 23, 12, 41, 50)
println fromDateNew.class
println fromDateNew
def result4 = db.activityLog.find(requestTime: ['$gte': fromDateNew]).count()

println result4

输出:

Mon Sep 23 12:41:50 BST 2013
class java.util.Date
1379936510544
0
196869
class java.util.Date
Sat Aug 23 12:41:50 BST 3913
0

【问题讨论】:

  • 似乎是类型不匹配。您是否尝试过只传递 fromDate 和 toDate(而不是 fromDateLong 和 toDateLong)?
  • @Lucasz Wiktor - 您好,感谢您的建议。是的,我刚刚尝试了 fromDate 和 toDate 并且得到了相同的结果 - 计数为 0。我将更新问题以包含此示例。

标签: mongodb gmongo


【解决方案1】:

您几乎“总是”希望在使用日期时进行“范围查询”。除非您绝对 知道实际的日期值,否则哪一种不符合要点。所以即使是这样的单个值:

"requestTime" : ISODate("2013-09-23T11:41:57.505Z"),

你真的想定义一个“小”范围,可能像:

db.activityLog.find({
    "requestTime": { 
        "$gte": new Date("2013-09-23 11:41:57"), 
        "$lt": new Date("2013-09-23 11:41:58")
    }
})

但是在你似乎想要做的事情的实际内容中(以及上面的说明)你需要做的是使用你"native " 传递给查询时“日期”类型的语言平台实现。

MongoDB 中的日期以 BSON 表示形式存储,该表示实际上是内部的“纪元”时间戳。因此,“驱动程序”将您的“本地”日期转换为这种表示形式。从集合中“读取”结果时也是如此,因此 MongoDB 存储的日期将转换为您的“本机”语言日期格式。

所以使用“本机”方式而不是转换为字符串。 ISODate 对象类型只是表示这些“对象”的一种 mongo“shell”方式。

【讨论】:

  • @Neill_Lunn,您好,感谢您的回复。我现在正在尝试这样做 - 请参阅我的问题的补充。我想我快到了,但令人困惑的是,我从 mongo 获得的日期时间会起作用,但我手动创建的日期时间不起作用,即使它们属于同一类。我不介意使用自纪元以来的时间并对此进行查询,但这似乎也不起作用。注意 - 我可以在 mongo shell 中执行此查询,但我也希望能够使用 gmongo 驱动程序以编程方式在 groovy 中执行此操作。
  • @Stuart 我确实认为这是您编辑中提到的课程。考虑到它是“Groovy”,它应该是基本的 java Date 类(scala 人更喜欢 Joda time)该翻译应该由驱动程序处理,请参阅here。所以也许包括一些你用来实际尝试这种类型的代码。
【解决方案2】:

问题在于Date constructor。第一个参数不是年份本身,而是 1900 + 年。这就是为什么你在 2013 年之后得到 3913。更重要的是月份从 0 而不是 1 开始 - 这解释了为什么你得到的是八月而不是九月。

【讨论】:

  • 供将来参考,这是使用 gmongo 驱动程序使用 groovy 对 mongo 进行日期时间查询的语法:def fromDate = Date.parse("yyyy-MM-dd'T'HH:mm:ss", "2013-09-23T11:41:50") println fromDate def result = db.activityLog.find(requestTime: ['$gte' : fromDate]).count() println result
猜你喜欢
  • 2014-08-29
  • 1970-01-01
  • 2011-08-30
  • 2010-12-20
  • 2021-08-17
  • 2015-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多