我偶然发现了MongoDB的一些非常奇怪的行为。对于我的测试用例,我有一个包含9个文档的MongoDB集合。所有文档都具有完全相同的结构,包括字段expired_at: Date
和location: [lng, lat]
。
我现在需要查找尚未过期且位于边界框内的所有文档;我在地图上显示匹配文件。为此,我设置了以下查询:
var qExpiry = {"expired_at": { $gt : new Date() } };
var qLocation = { "location" : { $geoWithin : { $box : [ [ 123.8766, 8.3269 ] , [ 122.8122, 8.24974 ] ] } } };
var qFull = { $and: [ qExpiry, qLocation ] };
由于过去的过期日期很长,当我将边界框设置得足够大时,以下查询会按预期为我提供所有9个文档:
db.docs.find(qExpiry);
db.docs.find(qLocation);
db.docs.find(qFull);
db.docs.find(qExpiry).sort({"created_at" : -1});
db.docs.find(qLocation).sort({"created_at" : -1});
现在这里有交易:以下查询返回0个文件:
db.docs.find(qFull).sort({"created_at" : -1});
只需在AND查询中添加排序就会破坏结果(请注意我要排序,因为我也有一个限制,以避免在较大比例上混乱地图)。按其他字段排序会产生相同的空结果。这里发生了什么?
(实际上甚至更奇怪:当我放大我的地图时,我有时会得到qFull
的结果,即使是排序。有人可能会说qLocation
有问题。但是当我只使用{{1结果始终是正确的。无论如何,qLocation
始终适用于所有文档。
答案 0 :(得分:2)
您可能希望尝试使用聚合框架 $match
和 $sort
管道运行相同的查询:
db.docs.aggregate([
{ "$match": qFull },
{ "$sort": { "created_at": -1 } }
]);
或通过指定以逗号分隔的表达式列表隐式使用 $and
db.docs.aggregate([
{
"$match": {
"expired_at": { "$gt" : new Date() },
"location" : {
"$geoWithin" : {
"$box" : [
[ 123.8766, 8.3269 ],
[ 122.8122, 8.24974 ]
]
}
}
}
},
{ "$sort": { "created_at": -1 } }
]);
不确定为什么失败了find()
答案 1 :(得分:1)
db.docs.aggregate(
[
{ $match : { $and : [qExpiry, qLocation]} },
{ $sort: {"created_at": -1} }.
{ $limit: 50 }.
]
);
尽管如此,如果有人能指出我的第一种方法不起作用,那将非常有用。只需将sort()
添加到非空查询中,就不应该突然返回0个文档。只是要添加,因为我仍然尝试了一点,.sort({})
返回所有文档,但不是很有用。其他一切都失败了,包括.sort({'_id': 1})
。