How does one represent MongoDB GeoJSON fields in a Mongoose Schema?
Solution 1
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
Solution 2
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)
Solution 3
The mongoose-geojson-schema package was created to make it easy to have GeoJSON in Mongoose Schemas.
Solution 4
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.
Solution 5
I'm about to start moving all my location references in my MongoDB from '2d'
to GeoJSON, so I'll encounter the same problem.
- Regarding the
type
problem, you have to follow what I did below to get it working. Mongoose correctly recognises it as a string. - Nested arrays; I agree that
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 ] }
] }
]
Aaron Silverman
SVP Engineering at Benefix.us. Co-creator of Doodle Or Die. Formerly Head of Engineering at stock media startup Storyblock, Senior Software Engineer at energy efficiency start-up Opower, and Lead Software Engineer at business analytic startup Applied Predictive Technologies. Washington, DC transplant to beautiful Ouray, Colorado via Philadelphia. Father to three children. Owner of two rescued dogs. Rock and Ice Climber. Instrument-rated private pilot.
Updated on July 09, 2022Comments
-
Aaron Silverman almost 2 years
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!