Reputation: 1696
I would to store a polygon inside a MongoDB document using mongoose. This is my schema:
var alarmSchema = new mongoose.Schema({
// ... some other fields ....
loc : {
"type": {
"type": String,
"enum": [
"Point",
"MultiPoint",
"LineString",
"MultiLineString",
"Polygon",
"MultiPolygon"
]
},
"coordinates": [[Number]]
}
});
So I've tried to add a new object of this type using:
var Alarm = db.model('Alarm', alarmSchema);
var alarmObj = new Alarm();
var polygonArray = [[10.371094,42.391009],[14.238281,44.024422],[16.259766,42.130821]];
alarmObj.loc = {type : "Polygon" , coordinates : polygonArray};
return alarmObj;
When i try to save this I get this error:
ValidationError: CastError: Cast to Array failed for value ....(the array passed)...
Any idea?
After that I would to find a list of these alarmObj which contains a passed point. I think this is the right query:
var geojsonPoint = { type: 'Point', coordinates: [44.95899,8.911711] }
AlarmModel.find({loc: { $geoIntersects: { $geometry: geojsonPoint}}},function(err,list) {});
Is it okay?
Upvotes: 1
Views: 3455
Reputation: 1440
I built this "Location Schema" and it seems to handle Points and Polygons:
var locationSchema = new Schema({
type: {
type: String,
enum: ['Point',
'MultiPoint',
'LineString',
'MultiLineString',
'Polygon',
'MultiPolygon'
],
default: 'Point'
},
coordinates: {
// Array of {lat,lng} objects
type: [{lat:{type:Number,max:90.0,min:-90.0},
lng:{type:Number,max:180.0,min:-180.0},
_id:false
}],
default: [{lat:0,lng:0}] // Lat Lon
}
},{_id:false});
var LocationModel = mongoose.model('Location',locationSchema);
// Test and validate polygon
var polygon = new LocationModel({
type:'Polygon',
coordinates:[{lat:-34.0,lng:105},{lat:-34.0,lng:106},
{lat:-35.0,lng:106},{lat:-35.0,lng:105}]
});
polygon.validate(function(err){
console.log(String(err));
});
// Test and validate point
var point = new LocationModel({
type:'Point',
coordinates:[{lat:-34.0,lng:105}]
});
point.validate(function(err){
console.log(String(err));
});
Hope this helps somebody.
EDIT:
After some work, for us, we ended up simplifying the 'Location' schema:
'use strict';
...
var schema = new Schema({
type: { // Type of Location
type: String,
required: true,
enum: ['Point','Polygon']
},
coordinates: { // Specified coordinates of location
type: [],
required: true
}
},{_id:false});
... validation methods, etc.
let model = mongoose.model('Location',schema);
module.exports = {
model : model,
schema : schema
}
Model that uses the Location Model/Schema:
const Location = require('./Location');
const LocationSchema = Location.schema;
...
const schema = new Schema({
...
location: {
type: LocationSchema,
required: true,
validate: [Location.someValidationMethod, 'Specified location is not a point']},
footprint: {
type: LocationSchema,
required: true,
validate: [Location.someValidationMethod, 'Specified location is not a Polygon']},
...
});
schema.index({'location','2dsphere'});
schema.index({'footprint','2dsphere'});
Test Driver:
let entry = new BlahModel({
...
location:{
type:'Point',
coordinates:[0,2] // Lon/Lat
},
footprint:{
type:'Polygon',
coordinates:[[[0,10],[0,20],[10,20],[0,10]]]
},
...
Upvotes: 3
Reputation: 71
Mongoose doesn't like the double array short hand [[Number]]
https://github.com/Automattic/mongoose/issues/1361
You'll want to define your geojson schema generically if you're trying to handle all those types, for example Points are just 1D arrays, LineStrings are 2D, and Polygons are 3D. Give this a shot:
geo: {
type: { type: String, "enum": [
"Point",
"MultiPoint",
"LineString",
"MultiLineString",
"Polygon",
"MultiPolygon"
] },
coordinates: { type: Array }
}
You can also check out some of these examples to help you get going: https://github.com/samluescher/geogoose https://github.com/rideamigoscorp/mongoose-geojson-schema
Hope this helps!
Upvotes: 1