Mongoose $near query returns parse error - node.js

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

Related

GeoJSON and Mongoose - Point must only contain numeric elements

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().

Cant make geospatial queries using polygon and point with mongoose

I'm trying to make a spatial query where in my database I have a collection with has area (a polygon) and i would like to find areas where cover this point.
Here is the GIST to test:
https://gist.github.com/mariohmol/0cfebdcbdd885bf71e6f79e629f8eb63
some parts of the code.
Schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var assert = require('assert')
console.log('\n===========');
console.log(' mongoose version: %s', mongoose.version);
console.log('========\n\n');
var dbname = 'testing_geojsonPoint';
mongoose.connect('localhost', dbname);
mongoose.connection.on('error', function () {
console.error('connection error', arguments);
});
var schema = new Schema({
loc: {
type: { type: String },
coordinates: []
},
area: {
type: { type: String, default: 'Polygon' },
coordinates: []
}
});
schema.index({ loc: '2dsphere' });
schema.index({ area: '2dsphere' });
var A = mongoose.model('A', schema);
I'm getting this error on mongoose version: 4.8.4:
//If I use this, works for the nearest
{ area: { $near: {
type: 'Point', coordinates: [-43.941932916641235,-19.931718548878326] }}}
//but if i do with geowithin it gives me the error:
{ area: {
$geoWithin: { $geometry: {
type: 'Point', coordinates: [-43.941932916641235,-19.931718548878326]
}}
Error: Invalid geoJSON type for $geoWithin "Point", must be "Polygon" or "MultiPolygon"
at cast (/node_modules/mongoose/lib/cast.js:159:25)

Deleting subdocuments using mongoose returning error?

I want to delete all the sub-documents of my collection.
mongoose schema :
//productSchema
var pdtSchema = new Schema({
"productId" : {type : String},
"product" : {type : String},
"item no" : {type : String},
});
var shopSchema = new Schema({
"providerId" : {type : String},
"provider" : {type : String},
"products" : [pdtSchema]
}, { collection:"shopdetails" });
module.exports.Shops = mongoose.model('Shops',shopSchema);
module.exports.Products = mongoose.model('Products',pdtSchema);
I have stored a bulk of data inside the collection and I need to delete all the products(that is the whole pdtSchema data).
code:
router.post('/delete',function (req,res) {
var providerId = req.body.providerId;
model.Shops.findById({"providerId" : providerId},function(err, doc) {
console.log(doc.products) // returns whole products here...
doc.products.remove();
doc.save(function(err,data){
res.json({"msg":"deleted"});
});
});
});
error:
(node:16351) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): ValidationError: CastError: Cast to ObjectID failed for value "[Function]" at path "_id"
Use the $unset operator which deletes the products field with the findOneAndUpdate() method. Using the traditional approach of first
retrieving the document with findById() only works with a valid ObjectId, in your case you are only providing a non-ObjectId string, hence the error.
router.post('/delete',function (req,res) {
var providerId = req.body.providerId;
model.Shops.findOneAndUpdate(
{ "providerId": providerId },
{ "$unset": { "products": "" } },
{ "new": true }
function(err, doc) {
console.log(doc) // returns modified doc here...
res.json({"msg": "Field deleted"});
}
);
});
If you want to keep the array field but remove all its elements, use $set as
router.post('/delete',function (req,res) {
var providerId = req.body.providerId;
model.Shops.findOneAndUpdate(
{ "providerId": providerId },
{ "$set": { "products": [] } },
{ "new": true }
function(err, doc) {
console.log(doc) // returns doc with empty products here...
res.json({"msg": "Products deleted"});
}
);
});
This is because you are saving "providerId" in shopSchema as type String, even though it is a mongoose object.
So, comparing a string type against a mognoose ObjectId type gives a cast error.
Instead do this,
var shopSchema = new Schema({
"providerId" : {
type : Schema.ObjectId
ref : schema which they are a reference to},
"provider" : {type : String},
"products" : [pdtSchema]
}, { collection:"shopdetails" });
But, I think if providerId refers to a shop Id, then it should be _id only.
model.findById() works with _id

MongoDB GeoJSON weird query results

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

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