Connecting to MongoDB
MongoEngine keeps named connections in a global registry: connect(name, host=...) opens (lazily) a connection under an alias, and documents declare which alias they use via meta = {"db": name}. The default alias is "default", so single-database applications need only one line. The patterns worth knowing: explicit aliases for multiple databases, lazy connections for testable code, and connection strings with credentials for anything beyond localhost.
The Basic Connection
from mongoengine import connect
# one call, default alias, database name first
connect("myapp", host="mongodb://localhost:27017")
Everything defined after this line that does not specify meta = {"db": ...} lives in the myapp database. The connection is created lazily - no socket opens until the first operation - so this line is cheap to call at import time, which is why it is conventionally placed in a db.py or settings module imported by the application.
Multiple Databases with Aliases
from mongoengine import connect, Document, StringField
connect("primary", host="mongodb://localhost:27017", alias="primary")
connect("analytics", host="mongodb://localhost:27017", alias="analytics")
class Order(Document):
meta = {"db": "primary", "collection": "orders"}
sku = StringField(required=True)
class EventLog(Document):
meta = {"db": "analytics", "collection": "events"}
name = StringField()
The alias keyword names the connection, and meta = {"db": "primary"} binds a document class to it. Querying Order.objects goes to primary, EventLog.objects to analytics - two databases, two concerns, one process. This is the standard pattern for splitting a hot operational store from an append-only analytics store without a second service.
Credentials and TLS
connect("myapp",
host="mongodb://user:[email protected]:27017,cluster1.example.com:27017/myapp?authSource=admin&ssl=true")
# the equivalent +srv form for Atlas (needs dnspython)
connect("myapp",
host="mongodb+srv://user:[email protected]/myapp?tls=true")
The connection string carries the whole policy: hosts, credentials, the auth database, and TLS. Keep the string in an environment variable - it contains a password - and use authSource when the user was created on a database other than the one being used. With ssl=true (or tls=true), pymongo negotiates TLS using the system CA store by default, which is all that managed clusters need.
Lazy Connections and Tests
from mongoengine import connect, disconnect, Document
# defer the actual socket to first use
connect("myapp", host="mongodb://localhost:27017", alias="myapp", lazy=True)
# in tests: a dedicated database, dropped between runs
connect("test", host="mongodb://localhost:27017/test_myapp")
# tear down a connection when done (e.g. in a test fixture)
disconnect("myapp")
lazy=True is the default and the right one for services: import-time connect calls register intent, and the first query pays the handshake cost. In tests, connect to a distinct test database (or a dedicated test instance) and disconnect in teardown so stale sockets never leak between cases.
Inspecting Active Connections
from mongoengine import get_connection, get_db, Connection
conn = get_connection() # the default alias
print(conn.db, conn.host)
db = get_db() # the underlying pymongo Database
print(db.name)
# every alias in the registry
from mongoengine.connection import _get_connection
print(list(_get_connection._connections))
These accessors are what you reach for in health checks, admin scripts, and debugging: confirm which database a connection is actually pointing at before you wonder why a query "found nothing".
Summary
Connect once per database with connect(db_name, host=...), use alias plus meta = {"db": ...} when a process talks to multiple databases, and put credentials and TLS policy in the connection string - read from the environment, never hardcoded. Keep connections lazy, point tests at a dedicated database, and use get_connection/get_db to verify where your queries are actually going.