旧版坐标对不以米为单位返回距离,而是以弧度为单位。因此,您的 maxDistance 远大于 50 公里。见Calculate Distances with Spherical Geometry
但也要考虑这里使用的实际距离:
db.getCollection('offers').aggregate([
{
$geoNear: {
near: [6.0950994999999999, 49.8914114000000026],
distanceField: "distance"
}
]);
返回:
{
"_id" : ObjectId("55dc0f4b6f07ad5d3ec3b6d0"),
"countryCode" : "DE",
"geoLocation" : [
{
"lat" : 50.8218537,
"lng" : 9.020215100000001
}
],
"distance" : 60.588259822017925
}
{
"_id" : ObjectId("55dc0f4b6f07ad5d3ec3b6cf"),
"countryCode" : "LU",
"geoLocation" : [
{
"lat" : 49.8914114,
"lng" : 6.0950995
}
],
"distance" : 61.93733827090219
}
因为“distanceField”是报告与查询点的投影距离的字段。
因此,起点是您的文档对于地理空间查询无效。像这样修复它们:
首先删除所有索引:
db.offers.dropIndexes();
然后修复字段:
var bulk = db.offers.initializeOrderedBulkOp(),
count = 0;
db.offers.find({}).forEach(function(doc) {
//printjson(doc);
var tmp = {
"type": "Point",
"coordinates": [doc.geoLocation[0].lng,doc.geoLocation[0].lat]
};
doc.geoLocation = tmp;
printjson(doc);
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "geoLocation": doc.geoLocation }
});
count++;
if ( count % 1000 == 0 ) {
bulk.execute();
bulk = db.offers.initializeOrderedBulkOp();
}
});
现在数据以正确的 GeoJSON 格式表示:
{
"_id" : ObjectId("55dc14856f07ad5d3ec3b6d1"),
"countryCode" : "LU",
"geoLocation" : {
"type" : "Point",
"coordinates" : [
6.0950995,
49.8914114
]
}
}
{
"_id" : ObjectId("55dc14856f07ad5d3ec3b6d2"),
"countryCode" : "DE",
"geoLocation" : {
"type" : "Point",
"coordinates" : [
9.020215100000001,
50.8218537
]
}
}
现在创建一个索引为 2dsphere:
db.offers.createIndex({ "geoLocation": "2dsphere" })
现在您可以查询了:
db.offers.aggregate([
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [6.0950994999999999, 49.8914114000000026]
},
"distanceField": "distance",
"spherical": true,
"maxDistance": 50000
}}
])
返回“近”的一个文档,或者实际上是 0 距离:
{
"_id" : ObjectId("55dc14856f07ad5d3ec3b6d1"),
"countryCode" : "LU",
"geoLocation" : {
"type" : "Point",
"coordinates" : [
6.0950995,
49.8914114
]
},
"distance" : 0
}