i want to query all user location with geoNear query like this
Campaign.where('uid','123')
.geoNear(point, { maxDistance : dist, spherical : true, distanceMultiplier:6378 },
function(err, data, stats){
if(err){
return handleError(res, err);
}
return res.json({
'stats': stats,
'data': data
})
});
but i get following error
TypeError: Object #<Query> has no method 'geoNear'
i want use geoNear because i need distance property with stats
Can i do this ??
pls Help
@programming-kid that's odd. What version of mongoose are you using? This should theoretically work...
mongoose: ~3.8.8
i tried updating to 3.8.13 but still i get following error
Object #<Query> has no method 'geoNear'
Yeah, Query
doesn't have geoNear
, so you have to use the fluent query syntax instead of .geoNear()
if you're going to use .where()
, here's some examples from the docs
how to get distance property if i use .where()
Here's how im doing it:
property.aggregate().near(
{
near:[parseFloat(req.params.longitude), parseFloat(req.params.latitude)],
distanceField:"distance",
spherical:true,
distanceMultiplier:3959,
maxDistance:parseFloat(req.params.distance)/3959,
query: {
monthlyFee : {
$gte: parseInt(req.params.minPrice),
$lte: parseInt(req.params.maxPrice)
},
numberOfBedrooms : { $gte: parseInt(req.params.minBedrooms) }
}
})
.exec(function(err,docs) {
if (err) res.send(err);
property.populate( docs, { path: 'user', select: 'firstname lastname email' }, function(err,properties) {
if (err) res.json(err);
res.json(properties);
});
});
Thanks @itaylorweb , not pretty but it gets jjob done.
@programming-kid @vkarpov15
how could I convert:
query = query.where('location.geocode')
.near({
center: [params.lng, params.lat],
maxDistance: params.distance * TO_RADIANS,
spherical: true
});
to .aggregate().near(?
My model is:
geocode: {
type: {type: String, default: 'Point'},
coordinates: []
},
Assuming you've created a 2dsphere index on location.geocode?
You can try:
location.aggregate().near(
{
near:[parseFloat(params.lng), parseFloat(params.lat)],
spherical:true,
distanceMultiplier:3959,
maxDistance:parseFloat(params.distance)/3959
})
.exec(function(err,docs) {
if (err) res.send(err);
res.json(properties);
});
Hey @itaylorweb
Ok, but I got other query.where happening before this filter
ex:
query = query.where('dateOfBirth').lte(now);
Having said that, should I do?
query = location.aggregate().near(
{
near: [parseFloat(params.lng), parseFloat(params.lat)],
spherical: true,
distanceMultiplier: 3959,
maxDistance: parseFloat(params.distance)/3959
});
The "coordinates" array is holding 2 values (long, lat)
Just build your query into the aggregate:
geocode in your model is a GeoJSON object so aslong as you've configured a 2dsphere index on geocode it should work.
var location = require('path to your location model');
location.aggregate().near(
{
near:[parseFloat(params.lng), parseFloat(params.lat)],
spherical:true,
distanceMultiplier:3959,
maxDistance:parseFloat(params.distance)/3959,
query: {
dateOfBirth : {
$lte: now
}
}
})
.exec(function(err,docs) {
if (err) res.send(err);
res.json(docs);
});
Example location schema:
var locationSchema = new Schema({
geocode: {
type: {type: String, default: 'Point'},
coordinates: []
},
dateOfBirth: Date
});
locationSchema.index({ geocode: '2dsphere' });
module.exports = mongoose.model('Location', locationSchema);
My only concerne is that I have a bunch of "query.where()" before the geo search.
query = User.find();
query.where()
query.where()
query.where()
The only way to make it work would be removing all the ".where" statements... Therefor making a single aggregation query?
Btw, thanks a lot for the help
I think thats what you need to do. Post the full code if you want. It may be straight forward.
No worries... It is just because is gonna be a big refectory process. I have 18 parameters, but that is fine. Thanks a lot @itaylorweb
I will test the aggregate now
Hey @itaylorweb
Should the following query do the job?
Model:
userSchema = new Schema({
name: String,
phone: String,
......
location: {
city: String,
state: String,
country: String,
geocode: {
type: {type: String, default: 'Point'},
// This is a length 2 array with longitude, latitude
coordinates: []
},
},
....
Query:
var newQuery =
User.aggregate().near(
{
near: [parseFloat(params.lng), parseFloat(params.lat)],
spherical: true,
distanceMultiplier: 3959,
maxDistance: parseFloat(params.distance)/3959
});
newQuery.exec().then(function (err, docs) {
console.log('ERR: ' + err);
console.log('Docs: ' + docs);
});
Btw, I do have a 2dsphere index on location.geocode... and my previous filter was working:
query = query.where('location.geocode')
.near({
center: [params.lng, params.lat],
// The distance is in radians: (actual travel distance) / earth_radius
maxDistance: params.distance * TO_RADIANS,
spherical: true
});
Looks ok to me. Have you ran it?
It didnt. :/
what error do you get?
Not sure if the .then is having an effect?
newQuery.exec(function (err, docs) {
console.log('ERR: ' + err);
console.log('Docs: ' + docs);
});
got it!
User.aggregate().near(
{
near: [params.lng, params.lat],
// The distance is in radians: (actual travel distance) / earth_radius
maxDistance: params.distance * TO_RADIANS,
spherical: true,
distanceField: 'distance'
});
Now it is working!
Glad it's working. Yep I have a distance field defined on my model: distance: Number, // Used to store distance when required
Thanks a lot @itaylorweb !
Just a quick note.
If you have query.where statements being executed before, you can get the generated condition list with " query._conditions".
query = query.where('location.city').equals(params.city);
query = query.where('location.country').equals(params.country);
query = User.aggregate().near(
{
near: { type: 'Point', coordinates: [params.lng, params.lat] },
distanceField: 'dist.calculated',
maxDistance: params.distance * TO_RADIANS,
query: query._conditions,
spherical: true
});
Most helpful comment
Here's how im doing it: