Revision 3edadd7196e1850835e341255e4f835a6e951ab3 authored by Valeri Karpov on 21 February 2022, 19:09:42 UTC, committed by Valeri Karpov on 21 February 2022, 19:09:42 UTC
1 parent 85361a4
geojson.md
# Using GeoJSON
<script>
_native.init("CK7DT53U",{
targetClass: 'native-inline'
});
</script>
<div class="native-inline">
<a href="#native_link#"><span class="sponsor">Sponsor</span> #native_company# — #native_desc#</a>
</div>
[GeoJSON](http://geojson.org/) is a format for storing geographic points and
polygons. [MongoDB has excellent support for geospatial queries](http://thecodebarbarian.com/80-20-guide-to-mongodb-geospatial-queries)
on GeoJSON objects. Let's take a look at how you can use Mongoose to store
and query GeoJSON objects.
<h2 id="points">Point Schema</h2>
The most simple structure in GeoJSON is a point. Below is an example point
representing the approximate location of [San Francisco](https://www.google.com/maps/@37.7,-122.5,9z).
Note that longitude comes first in a GeoJSON coordinate array, **not** latitude.
```
{
"type" : "Point",
"coordinates" : [
-122.5,
37.7
]
}
```
Below is an example of a Mongoose schema where `location` is a point.
```javascript
const citySchema = new mongoose.Schema({
name: String,
location: {
type: {
type: String, // Don't do `{ location: { type: String } }`
enum: ['Point'], // 'location.type' must be 'Point'
required: true
},
coordinates: {
type: [Number],
required: true
}
}
});
```
Using [subdocuments](/docs/subdocs.html), you can define a common `pointSchema` and reuse it everywhere you want to store a GeoJSON point.
```javascript
const pointSchema = new mongoose.Schema({
type: {
type: String,
enum: ['Point'],
required: true
},
coordinates: {
type: [Number],
required: true
}
});
const citySchema = new mongoose.Schema({
name: String,
location: {
type: pointSchema,
required: true
}
});
```
<h2 id="polygons">Polygon Schema</h2>
GeoJSON polygons let you define an arbitrary shape on a map. For example,
the below polygon is a GeoJSON rectangle that approximates the border
of the state of Colorado.
```
{
"type": "Polygon",
"coordinates": [[
[-109, 41],
[-102, 41],
[-102, 37],
[-109, 37],
[-109, 41]
]]
}
```
Polygons are tricky because they use triple nested arrays. Below is
how you create a Mongoose schema where `coordinates` is a triple nested
array of numbers.
```javascript
const polygonSchema = new mongoose.Schema({
type: {
type: String,
enum: ['Polygon'],
required: true
},
coordinates: {
type: [[[Number]]], // Array of arrays of arrays of numbers
required: true
}
});
const citySchema = new mongoose.Schema({
name: String,
location: polygonSchema
});
```
<h2 id="querying">Geospatial Queries with Mongoose</h2>
Mongoose queries support the same [geospatial query operators](http://thecodebarbarian.com/80-20-guide-to-mongodb-geospatial-queries)
that the MongoDB driver does. For example, the below script saves a
`city` document those `location` property is a GeoJSON point representing
the city of Denver, Colorado. It then queries for all documents within
a polygon representing the state of Colorado using
[the MongoDB `$geoWithin` operator](https://docs.mongodb.com/manual/reference/operator/query/geoWithin/).
<img src="https://i.imgur.com/i32pWnC.png">
```javascript
[require:geojson.*driver query]
```
Mongoose also has a [`within()` helper](/docs/api.html#query_Query-within)
that's a shorthand for `$geoWithin`.
```javascript
[require:geojson.*within helper]
```
<h2 id="geospatial-indexes">Geospatial Indexes</h2>
MongoDB supports [2dsphere indexes](https://docs.mongodb.com/manual/core/2dsphere/)
for speeding up geospatial queries. Here's how you can define
a 2dsphere index on a GeoJSON point:
```javascript
[require:geojson.*index$]
```
You can also define a geospatial index using the [`Schema#index()` function](/docs/api/schema.html#schema_Schema-index)
as shown below.
```javascript
citySchema.index({ location: '2dsphere' });
```
MongoDB's [`$near` query operator](https://docs.mongodb.com/v4.0/reference/operator/query/near/#op._S_near)
and [`$geoNear` aggregation stage](https://docs.mongodb.com/manual/reference/operator/aggregation/geoNear/#pipe._S_geoNear)
_require_ a 2dsphere index.
Computing file changes ...