使用这样的对象:
{
"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。
答案 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
但是,第一个查询将一个日期作为关键字,并为比较采用多个值。