MongoDB GeoJSON Schema Validation
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, aPoint
.coordinates
: An array of two decimal numbers. The first is thelongitude
and the second is thelatitude
.
{"_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}]}}}}}}