Python with MongoDB
NOTE: The official MongoDB documentation and the PyMongo Python library are essential resources for diving deeper. You can use this GitHub Codespaces to practice with MongoDB https://github.com/voirinprof/gis_starter_mongodb_geolab. For setting up a Codespaces environment, see Getting Started with GitHub Codespaces.
Introduction to MongoDB
MongoDB is a NoSQL document-oriented database. It stores data in BSON format (binary JSON), making it ideal for:
- Storing complex geographic objects
- Managing unstructured or semi-structured datasets
- Performing fast spatial queries via geospatial indexes
In geomatics, MongoDB is useful for:
- Storing large amounts of points, polygons, paths
- Performing proximity searches (e.g., finding all buses within a 1 km radius)
- Working with dynamic data (real-time streams)
Installing PyMongo
Install pymongo
in Python:
pip install pymongo
Tip: Use a virtual environment (
venv
) to isolate your dependencies.
Connecting to MongoDB in Python
from pymongo import MongoClient
# Connect to local MongoDB server
client = MongoClient('mongodb://localhost:27017/')
# Access the database and collection
db = client['geomatics']
collection = db['geospatial_points']
MongoDB automatically creates the database and collection if they do not exist.
Storing Geospatial Data
MongoDB natively supports geospatial types in GeoJSON format.
Example of inserting a point
document = {
"name": "Weather Station",
"location": {
"type": "Point",
"coordinates": [2.2945, 48.8584] # Longitude, Latitude
}
}
collection.insert_one(document)
Note: MongoDB expects coordinates in (longitude, latitude) order!
Creating a Geospatial Index
To perform efficient spatial queries, create a geospatial index:
collection.create_index([("location", "2dsphere")])
Searching for Nearby Objects
Example: Find all weather stations within a 5 km radius of a point:
center = [2.2945, 48.8584] # Longitude, Latitude (e.g., Eiffel Tower)
results = collection.find({
"location": {
"$near": {
"$geometry": {
"type": "Point",
"coordinates": center
},
"$maxDistance": 5000 # Distance in meters
}
}
})
for station in results:
print(station)
$near
performs an optimized search using the 2dsphere index.
Use Cases in Geomatics
1. Storing GPS Paths
A MongoDB document can contain an entire trajectory:
trip = {
"vehicle_id": "bus_42",
"path": {
"type": "LineString",
"coordinates": [
[2.2945, 48.8584],
[2.2950, 48.8585],
[2.2960, 48.8586]
]
}
}
collection.insert_one(trip)
2. Querying Objects Inside a Polygon (Area)
area = {
"type": "Polygon",
"coordinates": [[
[2.2930, 48.8570],
[2.2960, 48.8570],
[2.2960, 48.8600],
[2.2930, 48.8600],
[2.2930, 48.8570]
]]
}
results = collection.find({
"location": {
"$geoWithin": {
"$geometry": area
}
}
})
for obj in results:
print(obj)
$geoWithin
allows you to find all objects within a polygon.
3. Integrating MongoDB with Flask
MongoDB can be used as a database in a web application. While PostGIS is typically used in web applications, MongoDB can fulfill some aspects of the application. This database can be dedicated to the most frequent or system-demanding queries.
By combining Flask and MongoDB, we can offer a web service that relies on a NoSQL database.
from flask import Flask, jsonify, request
from pymongo import MongoClient
from bson import json_util
import os
import json
app = Flask(__name__)
client = MongoClient(os.environ.get('MONGO_URI'))
db = client.spatial_db
@app.route('/locations', methods=['GET'])
def get_locations():
locations = list(db.locations.find())
return jsonify(json.loads(json_util.dumps(locations)))
@app.route('/locations/near', methods=['GET'])
def get_nearby_locations():
try:
lon = float(request.args.get('lon'))
lat = float(request.args.get('lat'))
max_distance = float(request.args.get('max_distance', 1000)) # meters
locations = list(db.locations.find({
"location": {
"$near": {
"$geometry": {
"type": "Point",
"coordinates": [lon, lat]
},
"$maxDistance": max_distance
}
}
}))
return jsonify(json.loads(json_util.dumps(locations)))
except Exception as e:
return jsonify({"error": str(e)}), 400
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
Queries performed on the MongoDB database translate to JSON filters.
See the Flask web service example combined with MongoDB https://github.com/voirinprof/mongodb_docker
Best Practices
- Always index your geospatial fields for optimal performance.
- Follow the GeoJSON format: type + coordinates.
- Use additional filters to reduce the number of documents explored (
vehicle_id
,date
, etc.). - Consider schema validation (e.g., MongoDB allows enforcing constraints for expected fields).