Leigh Halliday
YouTubeTwitterGitHub

MongoDB GeoJSON Schema Validation

published Jul 6, 2020

If you want to save the location of someone, something, or somewhere, you'll need to store its coordinates. In this article we'll be looking at a Point, a singular location with latitude and longitude. We'll see how GeoJSON points should be stored in MongoDB to allow for geospatial queries efficiently, using geospatial indexes. And maybe more importantly, how can you use schema validation to ensure that the data entering your collection document's is valid?

Did you know there is a data structure specification for encoding data structures named GeoJSON? It allows you to define different types of geographic data such as a Point, LineString, Polygon, MultiPoint, MultiLineString, and MultiPolygon.

A Geographic Document in MongoDB

Storing a Point in a MongoDB Document requires the field to have a name. In our case it is called location, which is itself a document with two other fields:

  • type: One of the GeoJSON geographic types... in our case, a Point.
  • coordinates: An array of two decimal numbers. The first is the longitude and the second is the latitude.
{
"_id": {
"$oid": "5f0237bdcb57b0146028b79d"
},
"location": {
"type": "Point",
"coordinates": [-79.3832, 43.6]
}
// other fields
}

Querying Nearby Points

By applying a $near filter on the location field, we can find all points within 100km (100000 meters) of [-79.3832, 43.6532].

{
location: {
$near: {
$maxDistance: 100000,
$geometry: { type: "Point", coordinates: [-79.3832, 43.6532] },
},
},
};

Making Geospatial Queries Efficient

Geospatial queries become efficient by applying geospatial indexes to the fields containing geo data. The type of index that should be used in this case is a 2dsphere, applied to the location field. Voila!

Validating Points using MongoDB Schema Validation

To ensure that only valid points are entered into our database, we can add schema validation to this collection of locations which will require that the appropriate fields are always there, with the correct formats.

This schema validation requires that the location field exists, that it is an object with a type field with an enum value of Point, and a coordinates field of two numbers, the longitude between -180 and 180, and the latitude between -90 and 90. Thankfully json-schema has array Tuple validation which allows us to specify different validations for different positions of elements in the array, which is important in our case where it must be [longitude, latitude].

{
$jsonSchema: {
bsonType: 'object',
required: [
'location'
],
properties: {
location: {
bsonType: 'object',
required: [
'type',
'coordinates'
],
properties: {
type: {
bsonType: 'string',
'enum': [
'Point'
]
},
coordinates: {
bsonType: [
'array'
],
minItems: 2,
maxItems: 2,
items: [
{
bsonType: 'double',
minimum: -180,
maximum: 180
},
{
bsonType: 'double',
minimum: -90,
maximum: 90
}
]
}
}
}
}
}
}