Mongoose GeoNear - node.js

i'm building an api but i'm stuck now cause i can't find a way to make geo searches
Here's the model
var Event = new Schema({
idactivites : {
type: String,
required: true,
unique: true
},
nom: String,
description: String,
location : {
type : {
type: String,
default: "Point"
},
coordinates : {
type: [Number],
index: '2d'
}
},
created: {
type: Date,
required: false,
},
modified: {
type: Date,
default: Date.now
}
});
And here's the part of the code that processes my query
app.get('/api/geo_events', function(req, res) {
var latitude = req.query.latitude;
var longitude = req.query.latitude;
var radius = req.query.radius/6371 || 5000/6371;
var limit = parseInt(req.query.limit) || 20;
if(latitude && longitude)
{
var q = EventModelModel.find({'location': {
$near: [
longitude,
latitude
],
$maxDistance: radius
}
});
}
return q.exec(function (err, events) {
if (!err) {
return res.send(events);
}
});
});
Where am I wrong ?
I did not include here the parts in case of errors, but rest assured there are in my code.
Thanks in advance,
Jeremie.

Related

$geoNear give result only if I give maxDistance = 100 * 1000;

I want a list of Lawyers nearby,
I have used MongoDB aggregation but it gives results only if I pass maxDistance greater than 100km.
if I want to set maxDistance = 10 * 1000; then it is not giving any result but there are data available in the database.
this is model :
const mongoose = require('mongoose')
const Schema = mongoose.Schema;
const lawyerSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
location: {
type: { type: String, default: 'Point' },
coordinates: { type: [Number], default: [0, 0] }
}
})
lawyerSchema.index({ "location": "2dsphere" });
const Lawyer = mongoose.model('Lawyer', lawyerSchema)
module.exports = Lawyer
This is route :
//route for find nearby lawyer
router.get("/findLawyer", (req, res) => {
const long = parseInt(req.query.long);
const lat = parseInt(req.query.lat);
Lawyer.aggregate(
[
{
$geoNear: {
near: {
type: "Point",
coordinates: [long, lat],
},
distanceField: "dist",
minDistance: 10 * 1000,
maxDistance: 10 * 1000,
distanceMultiplier: 6371,
spherical: true,
key: "location",
},
},
],
(err, results) => {
if (err) {
res.status(400).json({ error: err });
} else {
res.status(200).json({ result: results });
}
}
);
});
This is record inside database :
This is my postman :
correct me if I made any mistake.
Thanks

Intersection of key values between 2 different collections in MongoDB

I have 2 collections: bookings and timeslots.
models/booking.js:
var mongoose = require ('../config/db');
var Schema = require('mongoose').Schema;
var ObjectId = Schema.ObjectId;
var bookingSchema = new Schema({
start: {
type: Number,
required: true
},
end: {
type: Number,
required: true
},
date: {
type: Date,
required: true,
default: Date.now
}
});
models/time_slot.js:
var mongoose = require ('../config/db');
var Schema = require('mongoose').Schema;
var ObjectId = Schema.ObjectId;
var timeSlotSchema = new Schema({
start: {
type: Number,
required: true
},
end: {
type: Number,
required: true
},
date: {
type: Number,
required: true,
default: Time.Today
},
enabled: {
type: Boolean,
required: true,
default: true,
},
pickup: {
type: Boolean,
required: true,
default: true,
}
});
Both have a field start in common. I would like to be able to get the entries from the collection timeslots in which the value of start has occurred in bookings.
I have tried:
controllers/time_slot.js:
var timeSlotModel = require('../models/time_slot').model;
var Booking = require('./booking');
Booking.getBookings({}, function(err, bookings) {
if (err) {
console.error(err);
} else {
timeSlotModel.find({start: bookings.start}, function(err, slots) {
if (err) {
console.error(err);
} else {
return next(null, slots);
}
}
}
But that doesn't work, unsurprisingly, and I get the error:
MongooseError: Cast to number failed for value "undefined" at path "start"
You can do it like this:
Booking.getBookings({}, function(err, bookings) {
if (err) {
console.error(err);
} else {
// build array with unique "start" values from bookings
var starts = bookings
.map(booking => booking.start)
.filter((val, i, self) => self.indexOf(val) === i)
// find by these start values
var query = {start: {$in: starts}}
timeSlotModel.find(query, function(err, slots) {
if (err) {
console.error(err);
} else {
return next(null, slots);
}
}
}

Query of mongoose mode.find near maxdistance not return correct results?

I want to perform geo search for coordinates and my code is in below:
location:{type:[Number],index: '2d'},
Shop.find({location:{$near:loc,$maxDistance: 5}}).limit(50).exec(function(err, doc) {
if (err) {
console.log(err);
}
callback(doc);
});
I set the maxDistance: 5 which should return me the point that within 5 km. But the actual results returned always contain points that distance is more than 5km(and even have point with distance of 500km more be returned).
what should i do?
the full code:
module.exports = function( mongoose) {
var ShopSchema = new mongoose.Schema({
shopName: { type: String, unique: true },
address: { type: String},
location:{type:[Number],index: '2d'},
shopPicUrl: {type: String},
shopPicTrueUrl:{type: String},
mark: { type: String},
open:{type:Boolean},
shopType:{type:String},
dish: {type: [{
dishName: { type: String},
tags: { type: Array},
price: { type: Number},
intro: { type: String},
dishPic:{ type: String},
index:{type:Number}
}]}
});
var Shop = mongoose.model('Shop', ShopSchema);
var createShop = function(shopName, address,location, shopPicUrl, open,shopType,res, callback) {
var shopInstance = new Shop({
shopName: shopName,
address: address,
location: location,
shopPicUrl: shopPicUrl,
open:open,
shopType:shopType
//shopPicTrueUrl:shopPicTrueUrl
});
shopInstance.save(function(err){
callback(err);
});
};
return {
createShop: createShop
}
}
Try this
var calculatedMaxDistance = (5) / 6371;
/EARTHRADIUSIN KM
Shop.find(
{
'geo': {
$near: [lat,long],
$maxDistance: calculatedMaxDistance
}
}
)
Refer this for radian calculation https://docs.mongodb.org/manual/tutorial/calculate-distances-using-spherical-geometry-with-2d-geospatial-indexes/

Mongoose: value from Model

I have the following model:
var requestSchema = new Schema({
description: { type: String, required: true },
country: { type: String, index: true },
shipping: [shipping],
deliveryLoc: { type: String, index: true },
price: { type: Number, default: 0 },
})
I now want to get the price using mongoose and I am not sure which command I have to use.
I tried:
var pricy = _.first(_.where(request.price));
and it does not work, I get undefined even through through other queries in the same file I can get "shipping".
Getting the shipping type works with the following command:
var shipping = _.first(_.where(request.shipping, { type: shippingType }));
Am I using the wrong command?
You should be able to use the select method as follows:
// find a request
var query = Request.findOne();
// selecting the `price` field
query.select('price');
// execute the query at a later time
query.exec(function (err, request) {
if (err) return handleError(err);
console.log('The price is $%s.', person.price) // The price is $6.92
});
or if passing a callback:
var Request = mongoose.model('Request', requestSchema);
// find each request with a country matching 'Zimbabwe', selecting the `price` field
Request.findOne({ 'country': 'Zimbabwe' }, 'price', function (err, request) {
if (err) return handleError(err);
console.log('The price is $%s.', request.price) // The price is $6.92.
});
First, you need to create your schema like that:
var items = new Schema({
description: { type: String, required: true },
country: { type: String, index: true },
shipping: [shipping],
deliveryLoc: { type: String, index: true },
price: { type: Number, default: 0 },
});
After that you need to compile the new schema and add it to the database:
items = mongoose.model("Items", items); // The table name will be "Items"
When the model is created, you can execute your query (find or findOne):
items.findOne({price: request.price}, function (error, item) {
if (error) {
console.log(error);
} else {
console.log(item);
}
});
The full code:
var mongoose, Schema;
mongoose = require("mongoose");
Schema = mongoose.Schema;
var items = new Schema({
description: { type: String, required: true },
country: { type: String, index: true },
shipping: [shipping],
deliveryLoc: { type: String, index: true },
price: { type: Number, default: 0 },
});
items = mongoose.model("Items", items);
items.findOne({price: request.price}, function (error, item) {
if (error) {
console.log(error);
} else {
console.log(item);
}
});

Execute method for every doc found

I want to execute isAparticipant method before I send the json data and I dont know the right way to do it and event.find() return a json and not an instance of the model and I think If i do a forEach on evts (JSON data) it's a bad idea.
Controller:
var Event = require('../../model/event');
var eventsController = {
// Get Events List
index: function(req, res){
// var currentUser = req.user;
Event.find(function(err, evts){
if(err){
res.status(400).json({success: false, errors: err.errors});
}else{
res.status(200).json({success: true, events: evts});
}
});
}
};
// Export eventsController
module.exports = eventsController;
Model:
var mongoose = require('mongoose');
var EventsSchema = new mongoose.Schema({
title:{
type: String,
unique: true,
required: true,
},
teaser: {
type: String,
required: true
},
description: {
type: String,
required: true
},
participants: [{type: mongoose.Schema.Types.ObjectId, ref: 'User'}],
start_date: {
type: Date,
required: true
},
end_date: {
type: Date,
required: true
},
lat: {
type: String,
required: true
},
lng: {
type: String,
required: true
},
created_at: {
type: Date,
default: Date.now
},
updated_at: {
type: Date,
default: Date.now
}
});
// Check If User is A particpant
EventsSchema.methods.isAparticipant = function(userId) {
if(this.participants.indexOf(mongoose.Schema.Types.ObjectId(userId)) != -1){
this.isParticipant = true;
}else{
this.isParticipant = false;
}
};
var Evt = mongoose.model('Event', EventsSchema);
module.exports = Evt;
As evts is an array, you can perform a forEach function to loop over the array in a synchronous manner:
evts.forEach(function(evt) {
evt.isParticipant(req.user.id);
});
res.status(200).json({success: true, events: evts});

Resources