Reputation: 2039
somehow I'm going crazy, but let me explain. I have a collection of documents where each document has a GPS-coordinate in the field "loc" (example below). Now I would like to query for all documents which are in a specific area. When I do the query using MongoShell I get correct results, but when I try it using Mongoose, every single attempt fails.
As you can see below I tried different attempts using 2 and 3 [] around the Polygon coordinates.
MongoDB Version: 2.6.3 Mongoose Version: 3.8.13
Maybe someone can help me find the type or some other stupid mistake I don't see ;-( Sadly the error message "undefined is not a function" does not help very much.
Thanks!
Mongoose-Schema
(function () {
module.exports = function (mongoose, Schema) {
var PointSchema = new Schema({
_id: Schema.ObjectId,
loc: {
type: { type: String },
coordinates: { type: [Number]}
}
}, { collection: "points" });
PointSchema.index({ loc: "2dsphere" });
mongoose.model("Point", PointSchema);
};
})();
Sample document from the collection
{
"_id": ObjectId("53d0d30c92a82799d8ed31d2"),
"loc": {
"type": "Point",
"coordinates": {
"0": 8.5652166666667,
"1": 49.3288
}
}
}
Mongo-Shell script which works Based on: http://docs.mongodb.org/manual/reference/operator/query/geoWithin/#op._S_geoWithin
db.points.find( { loc :
{ $geoWithin :
{ $geometry :
{ type : "Polygon" ,
coordinates : [[[8.594874265234353, 49.33654935186479],
[8.594874265234353, 49.322858939564284],
[8.553675534765603, 49.322858939564284],
[8.553675534765603, 49.33654935186479],
[8.594874265234353, 49.33654935186479]]]
} } } } )
1. Failed Mongoose attempt Errormessage: TypeError: undefined is not a function - Tryed to take the shell script and put it into "find"
var Point = mongoose.model("Point");
var pointFields = { '_id': 1, 'loc': 1 };
Point.find({
loc:
{
$geoWithin:
{
$geometry:
{
type: "Polygon",
coordinates: [[[8.594874265234353, 49.33654935186479],
[8.594874265234353, 49.322858939564284],
[8.553675534765603, 49.322858939564284],
[8.553675534765603, 49.33654935186479],
[8.594874265234353, 49.33654935186479]]]
}
}
}
}).select(pointFields).lean().exec(function (error, result) {
console.log("Error: " + error);
processResponse(error, result, response);
});
**2. Failed Mongoose attempt using 3[] ** Errormessage: MongoError: Can't canonicalize query: BadValue bad geo query - Based on: https://github.com/LearnBoost/mongoose/issues/2092
var geoJsonPoly = {
polygon: [[[8.594874265234353, 49.33654935186479],
[8.594874265234353, 49.322858939564284],
[8.553675534765603, 49.322858939564284],
[8.553675534765603, 49.33654935186479],
[8.594874265234353, 49.33654935186479]]]
};
var Point = mongoose.model("Point");
var pointFields = { '_id': 1, 'loc': 1 };
Point.find({}).where('loc').within(geoJsonPoly).select(pointFields).lean().exec(function (error, result) {
console.log("Error: " + error);
processResponse(error, result, response);
});
3. Failed Mongoose attempt using 2[] Errormessage: TypeError: undefined is not a function Based on: https://github.com/LearnBoost/mongoose/issues/2092 and http://mongoosejs.com/docs/api.html#query_Query-within
var geoJsonPoly = {
polygon: [[8.594874265234353, 49.33654935186479],
[8.594874265234353, 49.322858939564284],
[8.553675534765603, 49.322858939564284],
[8.553675534765603, 49.33654935186479],
[8.594874265234353, 49.33654935186479]]
};
var Point = mongoose.model("Point");
var pointFields = { '_id': 1, 'loc': 1 };
Point.find({}).where('loc').within(geoJsonPoly).select(pointFields).lean().exec(function (error, result) {
console.log("Error: " + error);
processResponse(error, result, response);
});
4.Failed Mongoose attempt Errormessage: MongoError: Can't canonicalize query: BadValue bad geo query - Tried to use a full GeoJSON using 2[] around coordinates
var geoJsonPoly = {
type: "Polygon",
coordinates: [[8.594874265234353, 49.33654935186479],
[8.594874265234353, 49.322858939564284],
[8.553675534765603, 49.322858939564284],
[8.553675534765603, 49.33654935186479],
[8.594874265234353, 49.33654935186479]]
};
var Point = mongoose.model("Point");
var pointFields = { '_id': 1, 'loc': 1 };
Point.find({}).where('loc').within(geoJsonPoly).select(pointFields).lean().exec(function (error, result) {
console.log("Error: " + error);
processResponse(error, result, response);
});
5. Failed Mongoose attempt Errormessage: TypeError: undefined is not a function - Tried to use a full GeoJSON using 3[] around coordinates
var geoJsonPoly = {
type: "Polygon",
coordinates: [[[8.594874265234353, 49.33654935186479],
[8.594874265234353, 49.322858939564284],
[8.553675534765603, 49.322858939564284],
[8.553675534765603, 49.33654935186479],
[8.594874265234353, 49.33654935186479]]]
};
var Point = mongoose.model("Point");
var pointFields = { '_id': 1, 'loc': 1 };
Point.find({}).where('loc').within(geoJsonPoly).select(pointFields).lean().exec(function (error, result) {
console.log("Error: " + error);
processResponse(error, result, response);
});
console.trace() returns
Trace
at Promise.<anonymous> (C:\Dev\Mobile\src\nodejs\analyze.js:336:17)
at Promise.<anonymous> (C:\Dev\Mobile\src\nodejs\node_modules\mongoose\node_modules\mpromise\lib\promise.js:172:8)
at Promise.EventEmitter.emit (events.js:95:17)
at Promise.emit (C:\Dev\Mobile\src\nodejs\node_modules\mongoose\node_modules\mpromise\lib\promise.js:84:38)
at Promise.reject (C:\Dev\Mobile\src\nodejs\node_modules\mongoose\node_modules\mpromise\lib\promise.js:111:15)
at Promise.error (C:\Dev\Mobile\src\nodejs\node_modules\mongoose\lib\promise.js:89:15)
at Promise.resolve (C:\Dev\Mobile\src\nodejs\node_modules\mongoose\lib\promise.js:107:24)
at Promise.<anonymous> (C:\Dev\Mobile\src\nodejs\node_modules\mongoose\node_modules\mpromise\lib\promise.js:172:8)
at Promise.EventEmitter.emit (events.js:95:17)
at Promise.emit (C:\Dev\Mobile\src\nodejs\node_modules\mongoose\node_modules\mpromise\lib\promise.js:84:38)
Upvotes: 1
Views: 3693
Reputation: 1513
The GeoJSON structure in your document seems incorrect. Try specifying the coordinates as an array:
{
"_id": ObjectId("53d0d30c92a82799d8ed31d2"),
"loc": {
"type": "Point",
"coordinates": [8.5652166666667, 49.3288]
}
}
This in combination with your fifth example should work. Also checkout the GeoJSON references on Point and Polygon regarding their structure.
Working example code:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
var PointSchema = new mongoose.Schema({
_id: mongoose.Schema.ObjectId,
loc: {
type: { type: String },
coordinates: { type: [Number] }
}
}, { collection: "points" });
PointSchema.index({ loc: "2dsphere" });
mongoose.model("Point", PointSchema);
var geoJsonPoly = {
type: "Polygon",
coordinates: [
[
[8.594874265234353, 49.33654935186479],
[8.594874265234353, 49.322858939564284],
[8.553675534765603, 49.322858939564284],
[8.553675534765603, 49.33654935186479],
[8.594874265234353, 49.33654935186479]
]
]
};
var Point = mongoose.model("Point");
var pointFields = { '_id': 1, 'loc': 1 };
Point.find({}).where('loc').within(geoJsonPoly).select(pointFields).lean().exec(function (error, result) {
console.log("Error: " + error);
console.log(result);
});
Upvotes: 3