0

所以我有一个集合来存储事件的开始和结束时间,我希望用户能够通过指定“过滤器”开始和结束时间来查询事件。查询应返回与过滤时间相交的任何事件。我以为我正在正确构建查询,但它没有返回我想要的结果。

示例数据(简化的 mongo 文档来理解,时间是 HHMMSS):

{ ..., "start" : "050520", "end" : "051309" } //Should match
{ ..., "start" : "051125", "end" : "051925" } //Should match
{ ..., "start" : "052049", "end" : "052420" } //Should match
{ ..., "start" : "050000", "end" : "050500" }
{ ..., "start" : "052100", "end" : "052721" }

我尝试的查询是(如果我在这里错过了括号,请原谅我,这不是问题):

find( { $or : [ 
            { start : { $gte : "050600", $lt : "052100" } }, 
            { end : { $lt : "052100", $gt : "050600" } } 
        ] } )

仅返回三个结果之一。切换 $or 部分的顺序(在开始时间之前查询结束时间)会给我两个结果,但不是全部三个。我似乎记得在应用查询的第二部分之前,对于复合查询,mongo 会丢弃与第一部分不匹配的结果,但我认为 $or 运算符会处理这个问题。有任何想法吗?我的查询不正确,这是在 mongo 中查询的限制吗?

4

2 回答 2

4

使用 MongoDB 2.4.5,我尝试了上述方法,并在两种情况下都返回了“应该匹配”结果的前 2 个。

我不认为应该返回第三个,因为它需要 ("052049" >= "050600" && "052049" < "052000") 或 ("052420" < "052000" && "052420" > "050600")两者都不为真。

MongoDB shell version: 2.4.5
connecting to: test
> 
> db.mycol.save({ "start" : "050520", "end" : "051309" }) 
> db.mycol.save({ "start" : "051125", "end" : "051925" })
> db.mycol.save({ "start" : "052049", "end" : "052420" }) 
> db.mycol.save({ "start" : "050000", "end" : "050500" })
> db.mycol.save({ "start" : "052100", "end" : "052721" })
>
> db.mycol.find( 
... { $or : 
... [ { $and : [ { start : { $gte : "050600" } }, { start : { $lt : "052000" } } ] }, 
...   { $and : [ { end : { $lt : "052000" } }, { end : { $gt : "050600" } } ] } 
... ] 
...     } )
{ "_id" : ObjectId("520528522683a40682f12b5c"), "start" : "050520", "end" : "051309" }
{ "_id" : ObjectId("520528522683a40682f12b5d"), "start" : "051125", "end" : "051925" }
> 
> 
> db.mycol.find( 
... { $or : 
... [     { $and : [ { end : { $lt : "052000" } }, { end : { $gt : "050600" } } ] } , 
...   { $and : [ { start : { $gte : "050600" } }, { start : { $lt : "052000" } } ] }
... ] 
...     } )
{ "_id" : ObjectId("520528522683a40682f12b5c"), "start" : "050520", "end" : "051309" }
{ "_id" : ObjectId("520528522683a40682f12b5d"), "start" : "051125", "end" : "051925" }
> 
于 2013-08-09T17:49:36.683 回答
1

您的查询应该可以正常工作,但第三个不应该因为两者都匹配start并且end超出范围。

但是,您可以更清楚、更简洁地编写查询:

db.test.find({ $or: [
    { start: { $gte: "050600", $lt : "052000" }}, 
    { end: { $lt: "052000", $gt: "050600" }}
]});
于 2013-08-09T17:53:18.557 回答