Skillversitas

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.