-
-
Save PascalAnimateur/b73617f0a27475fd4ccb to your computer and use it in GitHub Desktop.
module.exports.bootstrap = function(cb) { | |
// Ensure we have 2dsphere index on coordinates attribute of Place. | |
sails.models.place.native(function (err, collection) { | |
collection.ensureIndex({ coordinates: '2dsphere' }, function () { | |
// It's very important to trigger this callback method when you are finished | |
// with the bootstrap! (otherwise your server will never lift, since it's waiting on the bootstrap) | |
cb(); | |
}); | |
}); | |
}; |
module.exports.models = { | |
// Geospatial queries require MongoDB connection (sails-mongo) | |
connection: 'someMongodbServer' | |
}; |
/* Place model */ | |
module.exports = { | |
attributes: { | |
name: { | |
type: 'string', | |
required: true | |
}, | |
// This is the attribute used for the place's geolocation. | |
// Be careful to store it as [ lng, lat ] or else geoNear queries will give imprecise results. | |
coordinates: { | |
type: 'json', | |
required: true | |
} | |
}, | |
/** | |
* Find places closer than a certain distance (in km) from a specified location [ lng, lat ]. | |
* @param conditions | |
* JSON object should look like this: | |
* { | |
* lng: -72.213, | |
* lat: 45.012, | |
* maxDistance: 100, | |
* limit: 20, | |
* } | |
* | |
* @param callback (err, results) | |
* Returns an array of results (ordered by increasing distance), it looks like this: | |
* [ | |
* { | |
* dis: 10.321, | |
* obj: { JSON object of Place } | |
* }, | |
* { | |
* dis: 20.123, | |
* obj: { JSON object of Place } | |
* } | |
* ] | |
*/ | |
findNear: function (conditions, callback) { | |
Place.native(function (err, collection) { | |
if (err) return callback(err); | |
collection.geoNear({ | |
type: "Point" , | |
coordinates: [ conditions.lng, conditions.lat ] | |
}, { | |
limit: conditions.limit || 30, | |
maxDistance: conditions.maxDistance * 1000.0, | |
distanceMultiplier: 0.001, | |
spherical : true | |
}, function (err, places) { | |
if (err) return callback(err); | |
return callback(null, places.results); | |
}); | |
}); | |
} | |
}; |
/* Place controller */ | |
module.exports = { | |
/** | |
* Create two dummy places. | |
*/ | |
dummy: function (req, res) { | |
Place.create({ | |
name: 'New Richmond', | |
coordinates: [ -65.8716805, 48.1804069 ] | |
}, function (err, place) { | |
if (err) return res.negotiate(err); | |
console.log('Place created: ', place); | |
res.ok(); | |
}); | |
Place.create({ | |
name: 'Montreal', | |
coordinates: [ -73.5647636, 45.5158157 ] | |
}, function (err, place) { | |
if (err) return res.negotiate(err); | |
console.log('Place created: ', place); | |
res.ok(); | |
}); | |
}, | |
/** | |
* Find places closer than a certain distance (in km) from a specified location [ lng, lat ]. | |
*/ | |
search: function (req, res) { | |
// TODO: Default values and conditions validation should go in Place.findNear | |
var conditions = { | |
lng: parseFloat(req.param('lng')) || 0, | |
lat: parseFloat(req.param('lat')) || 0, | |
maxDistance: parseFloat(req.param('maxDistance')) || 1000, | |
limit: req.param('limit') || 30, | |
}; | |
Place.findNear(conditions, function (err, results) { | |
if (err) return res.negotiate(err); | |
return res.json(results); | |
}); | |
} | |
}; |
@Jamie452 @PascalAnimateur I am trying to do an app that tracks the user position and shows delivery vans that are nearest to them. I don't need to store the van location as its constantly changing. I am using Sails as a backend. The front end is 2 apps. 1 for the van driver which updates Sails every time its location changes significantly (0.5 kilometres). The other is a would be customer app and that just displays map pins of the closest van to them.
I am not very sure what this demands as its my first time doing such an app. After integrating your example above, my app looks like this:
// Location.js
module.exports = {
attributes: {
van_id: {
type: 'string',
required: true,
index: true
},
coordinates: {
type: 'json',
required: true
}
}
}
I would love to have some thoughts on what you think the best way to handle this would be? Thanks
@theCrab: For the customer app you need some way of getting a location from IP, you could use something like node-freegeoip.
Seems like an ambitious project for a newcomer to Sails.. good luck!
Thanks @PascalAnimateur. Works perfectly!
module.exports.bootstrap = function(cb) {
// Ensure we have 2dsphere index on coordinates attribute of Place.
sails.models.modelName.native(function (err, collection) {
collection.ensureIndex({ coordinates: '2dsphere' }, function () {
// It's very important to trigger this callback method when you are finished
// with the bootstrap! (otherwise your server will never lift, since it's waiting on the bootstrap)
cb();
});
});
};
its giving me error
error: Bootstrap encountered an error: (see below)
error: TypeError: Cannot read property 'native' of undefined
at Object.module.exports.bootstrap (E:\codes\backend\Masterbackend\config\bootstrap.js:17:32)
at Sails.runBootstrap (C:\Users\hp\AppData\Roaming\npm\node_modules\sails\lib\app\private\bootstrap.js:44:25)
at Sails.wrapper [as runBootstrap] (C:\Users\hp\AppData\Roaming\npm\node_modules\sails\node_modules\@sailshq\lodash\lib\index.js:3250:19)
at Sails.initialize (C:\Users\hp\AppData\Roaming\npm\node_modules\sails\lib\app\private\initialize.js:68:9)
at wrapper (C:\Users\hp\AppData\Roaming\npm\node_modules\sails\node_modules\@sailshq\lodash\lib\index.js:3250:19)
at C:\Users\hp\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:713:13
at iterate (C:\Users\hp\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:262:13)
at C:\Users\hp\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:274:29
at C:\Users\hp\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:44:16
at C:\Users\hp\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:718:17
at C:\Users\hp\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:167:37
at C:\Users\hp\AppData\Roaming\npm\node_modules\sails\lib\app\load.js:184:13
at C:\Users\hp\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:52:16
at C:\Users\hp\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:548:17
at C:\Users\hp\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:542:17
at _arrayEach (C:\Users\hp\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:85:13)
at Immediate.taskComplete [as _onImmediate] (C:\Users\hp\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:541:13)
at runCallback (timers.js:800:20)
at tryOnImmediate (timers.js:762:5)
at processImmediate [as _immediateCallback] (timers.js:733:5)
any help ????
Found Out Solution
module.exports.bootstrap = function(cb) {
// Ensure we have 2dsphere index on coordinates attribute of Place.
modelName.native(function (err, collection) {
collection.ensureIndex({ coordinates: '2dsphere' }, function () {
// It's very important to trigger this callback method when you are finished
// with the bootstrap! (otherwise your server will never lift, since it's waiting on the bootstrap)
cb();
});
});
};
using native via modelName solve the problem
There are three main things to be considered:
- The 2dsphere index needs to be created properly (As described in the bootstrap.js.
- The name of the coordinates fields must be exactly coordinates (not coord, coordinate, position, ...)
- The positions need to be inserted with [longitude, latitude] not with [latitude, longitude].
Thanks, this gist is really helpful!
Since .native() has been deprecated, the new bootstrap.js like below:
// Ensure we have 2dsphere index on coordinates attribute of Place.
var db = Place.getDatastore().manager;
var collection = db.collection('Place');
collection.ensureIndex({ coordinates: '2dsphere' }, () => {
// It's very important to trigger this callback method when you are finished
// with the bootstrap! (otherwise your server will never lift, since it's waiting on the bootstrap)
cb();
});
Implemented your update and everything is working perfectly now, thanks!
P.S GitHub didn't notify me of your comment, so thanks again for reaching out directly.