1

I have been having a lot of trouble getting geoNear to work in SailsJS.

In my UserController.js I am trying to make a geoNear query on the location field in my user model. It is defined as JSON with a 2d-index on it. Here is an example of the field's data:

"location" : { "type" : "Point" , "coordinates" : [ 42.8003 , -73.8808 ]}

In my UserController my geoSearch method looks like this:

 geoSearch: function(req, res) {
    //sails.log.verbose(req);
    var lat = req.param('lat');
    var lng = req.param('long');
    var limit = req.param('limit') || 50;
    var maxDistance = req.param('radius') || 5000; //meters
    sails.log.verbose('lat : ' + lat);
    sails.log.verbose('lng : ' + lng);
    sails.log.verbose('limit : ' + limit);
    sails.log.verbose('maxDistance : ' + maxDistance);
    if (!(lat && lng)) {
        //bad stuff
        res.badRequest('Missing lat or long!');
    } else {
        User.native(function(err, collection) {
          collection.geoNear(lng, lat, {
                    limit: limit,
                    maxDistance: maxDistance, // in meters
                    query: {}, // allows filtering
                    distanceMultiplier: 3959, // converts radians to miles (use 6371 for km)
                    spherical : true
          }, function(mongoErr, users) {
                  if (mongoErr) {
                      console.error(mongoErr);
                      res.send('_geoSearch failed with error='+mongoErr);
                  } else {
                      console.log('users=',users);
                      res.json(users.results);
                    }
             });
        });
    }
}

However, when I make a request such as:

http://localhost:1337/api/user/location/?lat=42.8003&long=-73.8808

I get the output:

verbose: lat : 42.8003
verbose: lng : -73.8808
verbose: limit : 50    
verbose: maxDistance : 5000
{ [MongoError: exception: 'near' field must be point]
  name: 'MongoError',
  errmsg: 'exception: \'near\' field must be point',
  code: 17304,
  ok: 0 }

I have been struggling with this for quite a while, any help or guidance would be appreciated.

Other information:

MongoDB ~3.0 SailsJS ~0.10

https://github.com/mongodb/node-mongodb-native/blob/dd7bb687749ffab6ec4c4a6b052ef2cdffc0d780/lib/mongodb/collection.js#L1446

http://docs.mongodb.org/manual/reference/command/geoNear/

Zach Leighton
  • 1,939
  • 14
  • 24
  • Am I supposed to know what `geoNear` is? Also, "current" is not a version. The error is fairly descriptive: you are sending mongo something other than a `point` type – Travis Webb Mar 08 '15 at 20:23
  • I specified the current version #, and the data is a point when I step through the debugger. I have tried legacy coordinate pairs as well. I also referenced geoNear in mongoDB spec for you. – Zach Leighton Mar 08 '15 at 20:27
  • Also, I've tried using .aggregate and other methods, always with the same error. – Zach Leighton Mar 09 '15 at 12:25

2 Answers2

2

I had the same problem, it is caused by:

However, when I make a request such as:

http://localhost:1337/api/user/location/?lat=42.8003&long=-73.8808

So when data is received in server side it's converted to "String". Try this to solve it:

    var latitude = parseFloat(req.param('lat'));
    var longitude = parseFloat(req.param('long'));

Hope this would be helpful.

1

I was having similar problems until I added this to my bootstrap.js file

module.exports.bootstrap = function(cb) {
  // Ensure we have 2dsphere index on Property so GeoSpatial queries can work!
  sails.models.stores.native(function (err, collection) {
    collection.ensureIndex({ loc: '2dsphere' }, function () {

      // It's very important to trigger this callack method when you are finished
      // with the bootstrap!  (otherwise your server will never lift, since it's waiting on the bootstrap)
      cb();

    });
  });

};

Basically you are ensuring that your collection has a 2d sphere key associated to it. Lastly in your model file don't forget to define the type of the key containing the geo coordinates as json as shown below:

module.exports = {

  attributes: {

    loc: {
      type: 'json'
    }

  }
};

Hopefully it helps. Take care.

Ady Ngom
  • 1,284
  • 2
  • 10
  • 12
  • I tried that, I've decided I'm going to move forward with another technology as the support for Sails seems pretty limited at this time – Zach Leighton Mar 30 '15 at 20:01
  • 1
    Sad to hear, it worked for me and the speed is simply amazing. From 100 entries to 5000 entries with no noticeable lag in speed. I will stress test it tonight with 30000 entries. Hopefully you will come back to it sometimes. I surely am not going back to anything else. FYI this is for a live in production site, no pet project. Take care. – Ady Ngom Mar 30 '15 at 22:24