Can't use $near with String error in node express - node.js

I am getting error "Can't use $near with String error in node express" when we find records basis on longitude and latitude with maxDistance.
following is code, I am using:-
1-schema code:-
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var dtSchema = new Schema({
name:String,
date: {type: Date, default: Date.now},
location: { type: String, coordinates: [Number] },
category:String
});
//dtSchema.index({location: '2dsphere'});
module.exports = mongoose.model('places', dtSchema);
2-server.js code for fetch records
app.get('/location/:lon/:lat', function(req, res) {
console.log(req.params.lon);
console.log(req.params.lat);
location.find({location:
{ $near:
{
$geometry: { type: "Point", coordinates: [req.params.lon, req.params.lat ] },
$maxDistance: 5000
}
}}, function(err, places) {
if(!err){
res.send('({"records":' + JSON.stringify(places) + '});');
}
else{
console.log(err);
res.send("error coming")
}
});
});
parameter sending URL
http://localhost:4700/location/-73.9667/40.78
when we execute code and hit above URL. I found error "Can't use $near with String error in node express"

I had the same problem a while ago. The error is in the schema declaration.
var dtSchema = new Schema({
name:String,
date: {type: Date, default: Date.now},
location: {
type: {
type: String
},
coordinates: [Number]
},
category:String
});

db.location.aggregate([ { "$geoNear": { "near": { "type": "Point", "coordinates": [72.4468035,23.032069] }, "maxDistance": 500, "spherical": true, "distanceField": "distance" } } ])

The schema for geoNear should be
loc: {
type: {
type: String,
enum: ["Point"],
},
coordinates: {
type: [Number],
index: "2dsphere",
// 2dSphere supports queries that calculate geometries on an
// earth like sphere
},
},

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

Populate to join two collection in Mongodb gets null data

I am trying to create an API in node to get nearby users with the same pet_type.
UPDATE: After Reading the first answer and as per the documentation. I update my user model and I Tried using populate but it doesn't get me all the pets data of the user.
User Model
var UserSchema = new mongoose.Schema({
password: String,
first_name: String,
email: String,
location: {
type: { type: String },
coordinates: []
},
pets: {
type: mongoose.Schema.ObjectId,
ref:'Pet', default:null
}
});
Pet Model
var PetSchema = new mongoose.Schema({
name: String,
pet_type: String,
breed: String,
owner_id: {type: mongoose.Schema.ObjectId, ref:'User', default:null},
});
Current Query
var lat = req.query.lat;
var lng = req.query.lng;
User.find({
location: {
$near: {
$geometry: {
type: "Point",
coordinates: [lng, lat]
},
$maxDistance: 10000
}
},
_id:{ $nin :req.decoded._id }}, function(err, users) {
if(err) {
res.json({success:false, message:"No listing found", error:err});
return;
} else {
res.json({success:true, message:"User found", data:users});
return;
}
}).populate('pets');
output
{
"success": true,
"message": "Pet data",
"data": [
{
"location": {
"type": "Point",
"coordinates": [
72.53808,
23.02622
]
},
"pets": null,
"_id": "5f32cb544f6b1a07acd75f48",
"phone": "1234567890",
"email": "qwewqe#qwe.com",
"first_name": "qwertt",
}
]
}
You can use the .populate() method
Solution :
You can use lookup (aggregation) in mongodb
link : https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/
link : https://www.isummation.com/blog/perform-inner-join-in-mongodb-using-lookup-aggregation-operator/

How to use aggregate with $near mongoose?

I was trying to get random 20 foods near the particular location. When i used find it works but how to use aggregate with $near
Schema:
const foodSchema = new Schema({
foodName: {
type: String,
required: true
},
image: {
type: String,
required: true
},
price: {
type: String,
required: true
},
shopName: {
type: String,
required: true
},
isVerified:{
type:Boolean,
default:false,
required:true
},
isEnabled:{
type:Boolean,
default:false,
required:true
}
,
location: {
type: { type: String },
coordinates: [],
},
shopId:{
type: Schema.Types.ObjectId,
ref: 'Shop',
required: true
}
});
foodSchema.index({ location: "2dsphere" });
Food.aggregate([{$match:{isEnabled:true,location: {
$near: {
$maxDistance: 10000,
$geometry: {
type: "Point",
coordinates: [13.3339, 80.1943]
}
}
}}}])
.then(data=>{
console.log(data);
res.render('user/home',{
pageTitle:"UiMart",
foodlist:data
});
})
.catch(err=>{
console.log(err);
res.send("err");
});
MongoError: $geoNear, $near, and $nearSphere are not allowed in this context
How to use aggregate function with $near mongoose to get random foods near the particular location
Could you try something like this:
Food.aggregate
([
{
$geoNear: {
near: { type: "Point", coordinates: [13.3339, 80.1943] },
distanceField: "dist.calculated",
maxDistance: 10000,
query: { "isEnabled": true }
}
}
])
In the aggregation framework the $geoNear should be the first in the pipeline and you can use the query to filter the results instead of using match.

MongoDB - Whats wrong with how I create index?

I am trying to use Mongo's GeoSpatial features to locate documents based on coordinates.
I need to create indexes for it to work - but it seems like I can't get the index created? Can you help?
I'll walk through what I have so far.
//User saves the location using a PUT Command.
props.updateBandLocation({
geometry: {
type: "Point",
coordinates: [ lat, lon ]
}
})
Here is the route that puts it in the database. I try to get the index created here.
router.put('/:id', (req, res) => {
quoteGenerator.findByIdAndUpdate({_id: req.params.id}, req.body).then(() => {
quoteGenerator.findOne({_id: req.params.id}).then(generator => res.send(generator))
quoteGenerator.createIndex( { bandLocation: "2dsphere" } )
})
})
The indexing throws an error in my terminal but it creates the location anyways. Here it is in the database.
//How the query looks in the database
"bandLocation": {
"geometry": {
"type": "Point",
"coordinates": [
32.96179,
-96.82916850000001
]
}
},
Lastly, I am trying to get all the documents near a point using this route.
router.get('/allbands/:lat/:lng', (req, res) => {
quoteGenerator.find(
{
bandLocation:
{ $near: {
$geometry: {
type : "Point",
coordinates : [-req.params.lng, +req.params.lat],
}
}
}
}
).then(bands => res.json(bands))
});
Thanks for any help you have to offer!
Here is my schema --
//Create GeoSchema
const GeoSchema = new Schema({
geometry: {
type: {
type: String,
default: "Point",
index: "2dsphere",
},
coordinates: {
type: [Number],
},
}
})
//Create Schema - Band
const AutoQuoteGeneratorSchema = new Schema({
baseCost: {
type: Number
},
mainDate: {
type: Object
},
quoteGenerator: {
type: Array,
required: true,
},
userId: {
type: String,
required: true,
},
type: {
type: String,
required: true,
},
bandName: {
type: String,
required: true,
},
bandBio: {
type: String,
required: true,
},
bandLocation: GeoSchema,
bandTour: {
type: Array,
required: true,
},
bandGenre: {
type: String,
required: true,
},
youtube: {
type: Array,
required: true,
},
published: {
type: Boolean,
required: true,
},
posts: {
type: Array,
required: true,
},
});
Ok so from what i can see we have a couple of problems:
Structure:
From the 2dsphere index docs:
The 2dsphere index supports data stored as GeoJSON objects and legacy coordinate pairs
What type are GeoJSON objects?, they're { type: <GeoJSON type> , coordinates: <coordinates> }
And what type are legacy coordinates pairs? they're in the form of: [<longitude>, <latitude> ] or { <field1>: <x>, <field2>: <y> }
So we can see bandLocation is neither, you need to use
quoteGenerator.createIndex( { "bandLocation.geometry": "2dsphere" } )
Your Coordinates are in the wrong order, You need to specify in the order of longitude then latitude. The valid range of latitude in degrees is -90 and +90. Your value of latitude of -96 is out of range.
So change your document to [-96.82916850000001, 32.96179].
Now we just need to adjust your query:
quoteGenerator.find({
"bandLocation.geometry":
{ $near: {
$geometry: {
type : "Point",
coordinates : [-req.params.lng, +req.params.lat],
}
}
}
})
** Another thing that pops up is that you create (try to create) an index every time there's a function call when in-fact you should only do it once. it should not be a part of your code. Now this won't throw an error but it's redundant as Mongo auto index documents on changes / inserts.

geospatial queries on subdocuments

I have a mongoose schema with subdocuments that contain a location field (with 2dSpehre index). Like this:
var playerSchema = new mongoose.Schema({
name: { type: String, required: true },
addresses: [
{
address: {
street: String,
city: String,
zip: String,
country: String
},
loc: { type: [Number], index: '2dSphere' }
}
],
});
When I try to query for addresses via geospatial operators I get this error: planner returned error: unable to find index for $geoNear query. The query looks like this:
var query = {
'addresses.loc': {
$nearSphere: {
$geometry: { type: 'Point', coordinates: [16.3738189, 48.2081743] }
}
}
};
Player.find(query).exec();
I also checked via mongo that the index really exists:
> db.player.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "project.player"
},
{
"v" : 1,
"key" : {
"addresses.loc" : "2dsphere"
},
"name" : "addresses.loc_2dsphere",
"ns" : "project.player",
"2dsphereIndexVersion" : 2
}
]
What am I doing wrong? Thanks in advance.
Are you sure you are using the right collection? Mongoose will pluralize your collection name by default (so players instead of player).
The script below is working for me. For some reason Mongoose wasn't creating the 2dsphere index for me when it was specified in the schema so I moved that out.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var playerSchema = new mongoose.Schema({
name: { type: String, required: true },
addresses: [
{
address: {
street: String,
city: String,
zip: String,
country: String
},
loc: { 'type': { type: String }, 'coordinates': { type: [Number] } }
}
],
});
playerSchema.index({'addresses.loc': '2dsphere'});
var Player = mongoose.model('Player', playerSchema);
mongoose.connect('mongodb://localhost/test');
var query = Player.find({
'addresses.loc': {
$nearSphere: {
$geometry: { type: 'Point', coordinates: [16.3738189, 48.2081743] }
}
}
}, function (err, players) {
console.log(err)
console.log(players)
});

Resources