Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose find geo points by radius

I tried found geo points by radius, I found tutorial explain how to does it.

Snippet from tutorial:

First we need to create a schema. The docs give us some examples on how to store geospatial data. We are going to use the legacy format for our example. It’s recommended to store the longitude and latitude in an array. The docs warn use about the order of the values, longitude comes first.

var LocationSchema = new Schema({  
  name: String,
  loc: {
  type: [Number],  // [<longitude>, <latitude>]
  index: '2d'      // create the geospatial index
 }
});

First you can create a method in your controller that can look something like this:

findLocation: function(req, res, next) {  
    var limit = req.query.limit || 10;

    // get the max distance or set it to 8 kilometers
    var maxDistance = req.query.distance || 8;

    // we need to convert the distance to radians
    // the raduis of Earth is approximately 6371 kilometers
    maxDistance /= 6371;

    // get coordinates [ <longitude> , <latitude> ]
    var coords = [];
    coords[0] = req.query.longitude;
    coords[1] = req.query.latitude;

    // find a location
    Location.find({
      loc: {
        $near: coords,
        $maxDistance: maxDistance
      }
    }).limit(limit).exec(function(err, locations) {
      if (err) {
        return res.json(500, err);
      }

      res.json(200, locations);
    });
}

Reference to tutorial: How to use Geospatial Indexing in MongoDB with Express and Mongoose

After implemented source from tutorial to my project I didn't receive from database correct points by radius (points were not inside radius).

My question is how can I receive geo points by radius ( kilometers or meters don't matter)?

Thanks, Michael.

like image 717
Michael Horojanski Avatar asked Oct 31 '25 18:10

Michael Horojanski


1 Answers

I dealt with a similar problem a bit ago in my own database. It was tricky to dig around and find the answer, so I'll share it here. The geospatial element of Mongoose's DB package isn't well documented.

In the .find query, you need to use a more complex object than you have above. I found that the following construction works, where maxDistance is in meters and coords is an array of [longitude, latitude].

Location.find({
    loc: {
        $near: {
            $geometry: {
                type: "Point",
                coordinates: coords
            },
            $maxDistance: maxDistance
        }
    } 
}).then((err, locations) => {
    // do what you want here
})

This eliminates the need to deal with Earth's circumference and all that messiness. That is now native in Mongoose with this style of query. I've found that the function below is helpful to quickly make these queries so you don't have to deal with as much formatting each time.

var locQuery = (coords, distance) => {
    return { loc: { $near: { $geometry: { type: "Point", coordinates: coords }, $maxDistance: parseInt(distance)}}}
}
like image 66
Cole Ellison Avatar answered Nov 02 '25 07:11

Cole Ellison