使用两个日期比较而不是日期范围查询在MongoDB中给出不同的结果

时间:2015-06-17 07:52:54

标签: mongodb mongodb-query

使用这样的对象:

{
    "status" : 1,
    "date" : ISODate("2014-02-13T13:00:31.233Z")
}

为什么这个范围查询

db.collection.find({
    "status": 1,
    "date": {
    $lte: ISODate("2015-06-16T20:05:03.000Z"),
    $gte: ISODate("2015-06-15T20:05:03.000Z")
    }
});

给出正确的结果,而这两个日期比较给出了不同的结果:

db.collection.find({
    "status": 1,
    "date": {
    $lte: ISODate("2015-06-16T20:05:03.000Z")
    },
    "date": {
    $gte: ISODate("2015-06-15T20:05:03.000Z")
    }
});

看起来最后一个查询实际上最终是日期比较之间的OR,而不是我期望的AND。

2 个答案:

答案 0 :(得分:2)

这不相同的原因是因为您打破了适用于JavaScript对象的“哈希/映射”结构的一般规则。该规则规定,“密钥”只能指定一次

当你写下:

db.collection.find({
    "status": 1,
    "date": {
        "$lte": ISODate("2015-06-16T20:05:03.000Z")
    },
    // The next same key overwrites the other one
    "date": {
        "$gte": ISODate("2015-06-15T20:05:03.000Z")
    }
});

其中一个"date"项目被“忽略”,因为每个级别只能有一个。因此有效地将“小于”或“大于”作为条件抛弃(可能是“小于”,因为它是第一个)并且所有文档仅针对单个条件进行测试。

这是一个坚实的例子。请考虑以下文件:

{ "a": 1 },
{ "a": 2 },
{ "a": 3 },
{ "a": 4 }

发出此查询时:

 db.collection.find({ "a": { "$gte": 2 }, "a": { "$lte": 3 } },{ "_id": 0 })

结果仅与“第二”条件相匹配,因为该键覆盖了“第一”。它显然违反了“第一”条件,因此显示它被“丢弃”:

{ "a": 1 }
{ "a": 2 },
{ "a": 3 },

因此,为了应用两个条件,您需要像之前那样指定:

db.collection.find({
    "status": 1,
    "date": {
        "$lte": ISODate("2015-06-16T20:05:03.000Z"),
        "$gte": ISODate("2015-06-15T20:05:03.000Z")
    }
});

写这个本质上是“简写”:

db.collection.find({
    "status": 1,
    "$and": [
        { "date": {
            "$lte": ISODate("2015-06-16T20:05:03.000Z")
        }},
        { "date": {
            "$gte": ISODate("2015-06-15T20:05:03.000Z")
        }}
    ]
});

这是允许的,因为每个元素都在它自己的文档中,并且是数组的成员。在那里的分离允许您在每个元素中使用相同的键名。

答案 1 :(得分:0)

find({"status" : 1, "date":{ $lte:ISODate("2015-06-16T20:05:03.000Z")},"date":{$gte:ISODate("2015-06-15T20:05:03.000Z")}});

在这里您正试图找到日期(关键)小于2015-06-16T20:05:03.000Z并且在相同的查询中您是2015-06-15T20:05:03.000Z的日期(关键)。 您只有一个键作为日期。

以上查询的行为类似于select * from table where date> = 2015-06-15T20:05:03.000Z and date< = 2015-06-15T20:05:03.000Z

但是,第一个查询将一个日期作为关键字,并为比较采用多个值。