Mongoose version: 3.6 Node version: 0.10
I have been trying to solve this problem for hours. I want to find all the documents closer than maxDistance to some coordinates. I am trying to use the GeoJSON specifications of MongoDB (2dsphere), so that I can input the distance in meters.
This is my schema "venue.js":
var db = require('mongoose'),
Schema = db.Schema,
ObjectId = Schema.ObjectId;
var venueSchema = new Schema({
geo: { type: [Number], index: '2dsphere'},
city: String,
name: String,
address: String
});
module.exports = db.model('Venue', venueSchema);
This is where I insert the query ctrlVenue.js:
var Venue = require('../models/venue.js');
VenueController = function(){};
/** GET venues list ordered by the distance from a "geo" parameter. Endpoint: /venues
Params:
- geo: center for the list of venues - longitude, latitude (default: 25.466667,65.016667 - Oulu);
- maxDistance: maxímum distance from the center for the list of venues (default: 0.09)
**/
exports.getVenues =function(req, res) {
var maxDistance = typeof req.params.maxDistance !== 'undefined' ? req.params.maxDistance : 0.09; //TODO: validate
var geo = typeof req.params.geo !== 'undefined' ? req.params.geo.split(',') : new Array(25.466667, 65.016667); //TODO: validate
var lonLat = { $geometry : { type : "Point" , coordinates : geo } };
Venue.find({ geo: {
$near: lonLat,
$maxDistance: maxDistance
}}).exec(function(err,venues){
if (err)
res.send(500, 'Error #101: '+err);
else
res.send(venues);
});
}
When I run the code I receive the error:
"Error #101: CastError: Cast to number failed for value \"[object Object]\" at path \"geo\""
If I instead modify this line:
$near: lonLat,
with
$near: geo,
I correctly get the documents, but then, I cannot use meters as unit of measure. I based my assumptions on the following table: http://docs.mongodb.org/manual/reference/operator/query-geospatial/
I have seen plenty of functioning examples using $geometry but none together with $near. What am I doing wrong?
I had to use the Mixed
type and added some custom validation to ensure values were arrays and had a length of 2. I also checked for empty arrays and converted them to null
s because this is required when using sparse indices with 2dsphere
. (Mongoose helpfully sets array fields to [] for you, which is not a valid coordinate!)
var schema = new mongoose.Schema({
location: { type: {}, index: '2dsphere', sparse: true }
});
schema.pre('save', function (next) {
var value = that.get('location');
if (value === null) return next();
if (value === undefined) return next();
if (!Array.isArray(value)) return next(new Error('Coordinates must be an array'));
if (value.length === 0) return that.set(path, undefined);
if (value.length !== 2) return next(new Error('Coordinates should be of length 2'))
next();
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With