Reputation: 22635
MongoDB 2.4 allows the use of GeoJSON objects and a slew of neat functions and indexes that I'd like to use.
It expects GeoJSON objects to be stored in the format like:
loc: {
type: 'Polygon',
coordinates: [[[-180.0, 10.0], [20.0, 90.0], [180.0, -5.0], [-30.0, -90.0]]]
}
So in Mongoose one would think the schema would be defined like:
loc: { type: 'string', coordinates: [[['number']]] }
But this present two problems:
having a field called "type" screws up Mongoose's schema parsing because it allows defining fields in the form field: { type: , index: } etc.
Mongoose does not like nested arrays.
One way to overcome this is to simply use mongoose.Schema.Types.Mixed
, however I feel that there has got to be a better way!
Upvotes: 29
Views: 30679
Reputation: 4991
Mongoose now officially supports this.
In a nutshell, what you do is, for that schema, you use the typeKey
setting to tell mongoose to use a different key for type information. Here is an example:
var schema = new Schema({
// Mongoose interpets this as 'loc is an object with 2 keys, type and coordinates'
loc: { type: String, coordinates: [Number] },
// Mongoose interprets this as 'name is a String'
name: { $type: String }
}, { typeKey: '$type' }); // A '$type' key means this object is a type declaration
So now instead of declaring type info with the type
property, you use $type
. This works at the schema level so use it in the schemas that need it.
Upvotes: 5
Reputation: 13381
The mongoose-geojson-schema package was created to make it easy to have GeoJSON in Mongoose Schemas.
Upvotes: 5
Reputation: 20378
For reference, GeoJSON is officially supported in Mongoose 3.6
Example (from the docs):
new Schema({ loc: { type: [Number], index: '2dsphere'}})
... then ...
var geojsonPoly = { type: 'Polygon', coordinates: [[[-5,-5], ['-5',5], [5,5], [5,-5],[-5,'-5']]] }
Model.find({ loc: { $within: { $geometry: geojsonPoly }}})
// or
Model.where('loc').within.geometry(geojsonPoly)
Upvotes: 48
Reputation: 2730
I'm about to start moving all my location references in my MongoDB from '2d'
to GeoJSON, so I'll encounter the same problem.
type
problem, you have to follow what I did below to get it working. Mongoose correctly recognises it as a string.mongoose.Schema.Types.Mixed
will work, but I think you can try what I did below, let me know if it works. I'm not near a PC with mongo installed to try the schema out.Here's how I'd define the schema. The nested array can be tweaked to work, so let me know if it doesn't.
var LocationObject = new Schema ({
'type': {
type: String,
required: true,
enum: ['Point', 'LineString', 'Polygon'],
default: 'Point'
},
coordinates: [
[
{ type: [ Number ]
]
]
});
If you get undesired results in the nesting of the Array
, try this out instead. Basically nesting in deeper.
coordinates: [
{ type: [
{ type: [ Number ] }
] }
]
Upvotes: 4
Reputation: 10780
You must used Mixed to represent arrays of arrays. There is an open ticket to support this in the future.
@nevi_me is correct, you must declare the type
property as he described.
Here's a gist: https://gist.github.com/aheckmann/5241574
See the mongoose tests here for more ideas: https://github.com/LearnBoost/mongoose/blob/master/test/model.querying.test.js#L1931
Upvotes: 15