猫鼬$ maxDistance不准确

时间:2015-05-14 10:57:51

标签: node.js mongodb mongoose geolocation

我将地方存储在Mongoose模型中(名称+ coords为[lng,lat])并且在其上有一个2d索引。

我想从半径(km)内的点(lng,lat)获得最近的位置。

为此,我使用mongoose的$ near和$ maxDistance参数。 我面临的问题是半径似乎不准确,因此我得到错误的结果。

以下是我的地理搜索代码:

LocationModel.find({
        loc: {
            $near: coords,
            $maxDistance: max_distance
        }
    }).exec(function(err, locations)
    {
        if(err)
            return res.status(400).send({
                message: errorHandler.getErrorMessage(err)
            });

        res.json(locations);
    });

我的测试有两个位置:

  

地点1:6.614090000000033,45.4203

     

地点2:6.905578500000047,45.4683226

     

总距离:23.36km

$ maxDistance的max_distance以这种方式计算:

var max_distance = req.params.max_distance / 111.12;

当我提供参考点作为地点A时,我只有在将max_distance设置为33km及以上时才会得到结果,而不是应该是24km。

有人可以解释我这里有什么问题吗?也许是111.12(我在互联网上找到的),还是其他的东西?

由于

2 个答案:

答案 0 :(得分:4)

既然你在谈论地理定位,我会建议这些改变:

  1. 使用2dsphere索引代替2d。这将确保搜索考虑到地球不是二维平面。
  2. 更改模型以表示GeoJSON格式的坐标。
  3. 所以你的架构应该是这样的:

        var LocationSchema = new mongoose.Schema({
          name: String,
          location: {
            type: {
               type: String,
               default: "Point"
            },
            coordinates: {
                type: [Number]
            }
          }
        });
        LocationSchema.index({ location: '2dsphere' });
    

    现在,您可以使用here来执行查询。要以公里为单位,您需要使用distanceMultiplier选项,以地球半径(公里)为单位。不要忘记{ spherical: true }标志。

    注意:我已将它用作聚合的一部分,而且非常准确。它也应该在上述情况下也一样。 Mongoose文档没有谈论它。使用Model.geoNear

答案 1 :(得分:1)

在赤道上,1度是大约111公里,你的111.12来自。但是当我们离开赤道时,由于我们接近极点时经线(经度)的收敛,它变得更少。

Degree  Lat         Lng
0°      110.574 km  111.320 km
15°     110.649 km  107.551 km
30°     110.852 km  96.486 km
45°     111.132 km  78.847 km
60°     111.412 km  55.800 km
75°     111.618 km  28.902 km
90°     111.694 km  0.000 km

您可以使用equirectangular approximation

x = Δlat * cos (Δlng/2)
y = ΔLng
d = R ⋅ √x² + y²
where Δlat & Δlng in radians & R = radius of earth
Δlat is the difference between the 2 lats  & Δlng that of lats