Mongoose调用使用GeoJSON点作为查询参数的geoNear无法工作

4

给定一个定义了包含 GeoJSON 位置的文档的模式;


var BranchSchema = new Schema({
  location: {
    'type': {
      type: String,
      required: true,
      enum: ['Point', 'LineString', 'Polygon'],
      default: 'Point'
    },
    coordinates: [Number]
  },
  name: String
});
BranchSchema.index({location: '2dsphere'});

以下是一些示例数据:


[
  {
    "name": "A",
    "location": {
      "type": "Point",
      "coordinates": [153.027117, -27.468515 ] //Brisbane, Australia
    }
  },
  {
    "name": "B",
    "location": {
      "type": "Point",
      "coordinates": [153.029884, -27.45643] //Also Brisbane, Australia
    }
  }
]

以下的geoNear查询没有按照预期运行。我的理解是,这个查询是“给定一个南美海岸附近的位置,搜索所有位置并找出距离提供的位置在1米范围内的任何位置”。

// Somewhere off the east coast of South America.
var point = {type: 'Point', coordinates: [0.0776590, -33.7797590]};

Branch.geoNear(point, {maxDistance:1, spherical: true}, function (err, data) {
  ...
  // at this point I expected data.length === 0.
  // Instead it is returning both documents.
  ...
});

我做错了什么?

  • 按照WGS84标准,当定义位置时,我使用[经度,纬度]。
  • 正在使用MongooseJS V3.8.8。

此时我预期 data.length === 0,为什么你在这里期望一个文档?你没有在任何地方限制结果。 - Jayram
Jayram,我不期望有任何结果,因为集合中的这两个文档都应该距离[0.0776590,-33.7797590]的最大距离超过1。我认为我的查询表达式有问题,但我不知道是什么问题 :-) - Robert
我在使用mongoose的geonear时也遇到了同样的问题,它无法正常工作。我建议你手动实现或使用$near。 - Jayram
2个回答

4
问题是错误地使用了maxDistance。以下表达式可以正常工作。

Branch.geoNear({type: "Point", coordinates: [0.0776590, -33.7797590]}, {
  spherical: true, 
  maxDistance: 1 / 6378137, 
  distanceMultiplier: 6378137
})
  .then(function (doc) {
    console.log(doc);
    process.exit();
  });


Mongoose: branches.ensureIndex({ location: '2dsphere' }) { safe: undefined, background: true }  
Mongoose: branches.geoNear(0.077659) -33.779759 { distanceMultiplier: 6378137, lean: true, maxDistance: 1.567855942887398e-7, spherical: true } 
[]

现在查询正确地发现收集中的两个文档不在查询位置的1米范围内。查询更接近家的位置也给我们预期的结果。


Branch.geoNear({type: "Point", coordinates: [153.027117, -27.468515]}, {
  spherical: true, 
  maxDistance: 1 / 6378137, 
  distanceMultiplier: 6378137
})
  .then(function (doc) {
    console.log(doc);
    process.exit();
  });

Mongoose: branches.ensureIndex({ location: '2dsphere' }) { safe: undefined, background: true }  
Mongoose: branches.geoNear(153.027117) -27.468515 { distanceMultiplier: 6378137, lean: true, maxDistance: 1.567855942887398e-7, spherical: true } 
[ { dis: 0.0026823704060803567,
    obj: 
     { name: 'A',
       _id: 533200e49ba06bec37c0cc22,
       location: [Object],
       __v: 0 } } ]


解决方案是什么?
MongoDB文档中的geoNear说明,如果使用geoJSON对象,则maxDistance应该以米为单位,在使用坐标对时应该以弧度为单位。
可选参数。中心点距离的距离。对于GeoJSON数据,以米为单位,在传统坐标对中为弧度。MongoDB将结果限制为落在指定距离内的文档。这里是链接:http://docs.mongodb.org/manual/reference/command/geoNear/#dbcmd.geoNear 这要么是错误的,要么我的理解有误。 如上所述,与其为maxDistance指定1米,它以弧度的形式提供。
截至本帖发布日期,geoNear要求maxDistance始终以弧度为单位,而不管您是否使用geoJSON对象或传统坐标对。

2
关于此事,Github 上有一个未解决的问题:https://github.com/LearnBoost/mongoose/issues/1987 - Nick B
1
除掉distanceMultiplier选项后,我的距离计算结果才正确。然后我意识到它不再是弧度,而是米,MongoDB版本2.6.0,mongoose 3.8.8:distanceMultiplier: 1 - Rodrigo Polo
你好,能否帮我看看这个有50个奖励分的问题?https://dev59.com/Mek6XIcBkEYKwwoYBvbx 它与您曾经遇到的那个问题相关。我非常感谢任何帮助。 - AndreaM16

2
翻译如下:

由于本地驱动程序的限制,Mongoose 正在将 geoJSON 点转换为旧坐标对;已经添加了支持到本地驱动程序中,并且有一个开放的 PR来将此支持添加到 Mongoose 中。我已经更新了由 @NickB 提供的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接