Mongoose $ maxDistance not accurate

I am storing locations in Mongoose model (name + coords as [lng, lat]) and have a 2d index on it.

I want to get the closest locations from a point (lng, lat) in a radius in km.

For this I am using the mongoose $ near and $ maxDistance parameters. The problem I'm having is that the radius doesn't seem to be accurate, so I'm getting wrong results.

Here is my code for geo-search:

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);
    });

      

I have two places for my tests:

Seat 1: 6.614090000000033, 45.4203

Seat 2: 6.905578500000047, 45.4683226

Total Distance: 23.36km

The maximum value for $ maxDistance is calculated as follows:

var max_distance = req.params.max_distance / 111.12;

      

When I provide the pivot point as Place A, I only get results when max_distance is set to 33 km or more, not 24 km as it should be.

Can someone explain to me what is wrong here? Maybe 111.12 (which I found all over the internet), or is it something else?

thank

+3


source to share


2 answers


Since you are talking about geolocation, I would suggest the following changes:

  • Use 2dsphere

    index instead of 2d

    . This ensures that the search takes into account that the ground is not a 2d plane.
  • Modify your model to represent the coordinates in GeoJSON format.

So your diagram should look something like this:



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

      

Now you can use Model.geoNear to fulfill your request. To get the distance in kilometers, you need to use the option distanceMultiplier

with the radius of the earth in kilometers as the value. Don't forget the flag { spherical: true }

.

Note. I used it as part of the aggregation and is pretty accurate. In this case, it should work the same way. Mongoose documentation doesn't mention this. Use this from MongoDB docs

+3


source


1 degree is about 111 km at the equator, where your 111.12 comes from. But when we move away from the equator, it becomes smaller due to the convergence of the meridians (longitude) as we approach the pole.

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

      



For this, you can use an equal-shelving 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 

      

+1


source







All Articles