I am using GeoJSON to store coordinates of locations that i want later on to query by proximity,
my schema looks like the following:
'use strict';
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var BranchSchema = new Schema({
parentId: {
type: Schema.Types.ObjectId,
required: 'The ID of the restaurant is required.',
index: true
},
name: {
type: 'String',
required: 'The name is required.'
},
loc: {
'type': {
type: 'String',
default: 'Point'
},
coordinates: {
type: [Number],
default: [0,0]
}
}
});
BranchSchema.index({loc: "2dsphere"});
module.exports = mongoose.model('Branch', BranchSchema);
I am using mongoose and my query looks something like the following:
Branch.where('loc').near({
center: [long, lat],
maxDistance: proximity,
spherical: true
}).exec(function (err, branches) {
if (err) {
return res.status(400)
.send({
message: errors.getErrorMessage(err)
});
}
return res.json(branches);
});
i added a new branch to the database with the following coordinates Latitude:34.237918
Longitude:36.002197
and i query the database with the following coordinates:
Latitude:33.882957
Longitude:35.502319
and a maxDistance of 100
the difference between these 2 coordinates is more than 100m however the database return results, what am i missing???
Can you double check that you're doing the query that you think you are doing? Your query works fine for me:
> db.test.drop()
> var p = { "type" : "Point", "coordinates" : [36.002197, 34.237918] }
> var q = { "type" : "Point", "coordinates" : [35.502319, 33.882957] }
> db.test.insert({ "loc" : p })
> db.test.ensureIndex({ "loc" : "2dsphere" })
> db.test.count({
"loc" : {
"$near" : {
"$geometry" : q,
"$maxDistance" : 100
}
}
})
0
Related
I'm getting the following error:
MongoError: Can't extract geo keys: { _id: ObjectId('5aba6a88d366dbbf6c83a5d3'), gpshits: [ { coordinates: [ 6.982654547382455, 46.88414220428685 ], _id: ObjectId('5aba6a8fd366dbbf6c83a5d4'), type: "Point" } ], licenseplate: "xxaa22", createdAt: new Date(1522166408205), updatedAt: new Date(1522166415372), __v: 0 } Point must only contain numeric elements
Is it because i'm incorrectly nesting my Point in the model? I've read the docs but i cant find an example how to properly target the array. It's not giving any errors. Mainly trying to keep a log of GPS hits on a vehicle license plate number.
Model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var VehicleSchema = new Schema({
licenseplate: {type: String, required: true, unique:true},
gpshits : [{
type: { type: String },
coordinates:[mongoose.Schema.Types.Mixed]
}]
},
{
timestamps: true
}
);
VehicleSchema.index({'gpshits' : '2dsphere'});
module.exports = mongoose.model('Vehicle', VehicleSchema);
Function:
function (req, res) {
Joi.validate(req.body, Schemas.gpshit)
.then(function () {
return Vehicle.update({
licenseplate: req.body.licenseplate
}, {
$push: {
'gpshits': req.body.hit
}
}).exec();
})
.then(function () {
return res.status(200).json({
success: true
});
})
.catch(function (err) {
console.log(err)
return res.status(err.statusCode).json(err);
});
}
POST body:
{
"licenseplate": "xxaa22",
"hit" : {
"type" : "Point",
"coordinates": [6.982654547382455, 46.88414220428685]
}
}
Use parseFloat where you Insert the lattitude and longitude in mongoDB
var vehicle = new vehicle({
"licenseplate": licenseNumber,
"loc": {
"type": "Point",
"coordinates": [parseFloat(lng), parseFloat(lat)]
}
});
vehicle.save();
I fixed this by separating the array object into it's own schema and properly setting the coordinates field to '2dsphere' using index().
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
},
},
I have model, where car property is optional, but there is some property in car nested document, which should be required if User has car, like cartype : {required: true}, but when car is defined.
var UserSchema = new Schema({
email: {
type: 'String',
required: true
},
car: {
carType: {
// should be required if user have car
type: 'Number',
default: TransportType.Car
},
}
})
If there is no default value for carType, we can define one function hasCar to required of carType as below
var UserSchema = new Schema({
email: {
type: 'String',
required: true
},
car: {
carType: {
type: 'Number',
required: hasCar,
//default: TransportType.Car
},
}
});
function hasCar() {
return JSON.stringify(this.car) !== JSON.stringify({});//this.car; && Object.keys(this.car).length > 0;
}
With test codes
var u1 = new UUU({
email: 'test.user1#email.com'
});
u1.save(function(err) {
if (err)
console.log(err);
else
console.log('save u1 successfully');
});
var u2 = new UUU({
email: 'test.user1#email.com',
car: {carType: 23}
});
u2.save(function(err) {
if (err)
console.log(err);
else
console.log('save u2 successfully');
});
Result:
{ "_id" : ObjectId("56db9d21d3fb99340bcd113c"), "email" : "test.user1#email.com", "__v" : 0 }
{ "_id" : ObjectId("56db9d21d3fb99340bcd113d"), "email" : "test.user1#email.com", "car" : { "carType" : 23 }, "__v" : 0 }
However, if there is default value of carType, here maybe one workaround
var UserSchema = new Schema({
email: {
type: 'String',
required: true
},
car: {
carType: {
type: 'Number',
required: hasCar,
default: 1
},
}
});
function hasCar() {
if (JSON.stringify(this.car) === JSON.stringify({carType: 1})) {
this.car = {};
}
return JSON.stringify(this.car) === JSON.stringify({});
}
UserSchema.pre('save', function(next){
// if there is only default value of car, just remove this default carType from car
if (JSON.stringify(this.car) === JSON.stringify({carType: 1})) {
delete this.car;
}
next();
});
With the above test codes, results are
{ "_id" : ObjectId("56db9f73df8599420b7d258a"), "email" : "test.user1#email.com", "car" : null, "__v" : 0 }
{ "_id" : ObjectId("56db9f73df8599420b7d258b"), "email" : "test.user1#email.com", "car" : { "carType" : 23 }, "__v" : 0 }
This is an object example:
{
"_id" : "581994",
"type" : "Feature",
"geometry" : {
"type" : "Point",
"coordinates" : [
-149.0133,
64.7439
]
}
}
This is the query I execute:
Earthquake
.find({
geometry: {
$near: {
$geometry: {
type: 'Point',
coordinates: [lon, lat]
}
}
}
})
.exec(function(err, results) {
if (err) {
console.log(err);
}
return reply(results);
})
and this is the model schema I have created:
var mongoose = require('mongoose');
mongoose.set('debug', true);
var Schema = mongoose.Schema;
var earthquakeSchema = new Schema({
geometry: {
type: String,
coordinates: [Number]
}
});
earthquakeSchema.index({
geometry: '2dsphere'
});
var Earthquake = mongoose.model('Earthquake', earthquakeSchema);
module.exports = Earthquake;
From my perspective it seems correct but when I execute it I get always the same error:
[Error: Can't use $near with String.]
I don't find where is the mistake. I have checked everywhere
Ok I have found out the solution:
I have to add default field corresponding to 'Point' to property 'type'. Now it works
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)
});