Add a field with a default¶
Situation: you add status: str = "active" (and an optional plan) to a model. Existing
documents don't have them yet.
1. Change the model¶
@collection("users", indexes=[Index("email")])
class User(BaseModel):
name: str
email: str
status: str = "active" # new
plan: str | None = None # new, optional
2. See what MongoMig detects¶
$ mongomig diff
Schema changes (models vs migrations/schema_snapshot.json):
USERS
+ status: string = 'active' REQUIRES_DATA_MIGRATION backfill existing documents with 'active'
+ plan: string | null = None SAFE defaults to None: existing documents need no backfill
1 REQUIRES_DATA_MIGRATION · 1 SAFE
Generate a migration with: mongomig revision --autogenerate -m "describe it"
statushas a default, so existing documents get it written (backfill). Otherwise queries such as{"status": "active"}would miss every old document.plandefaults toNone. Old documents already read asNone, and{"plan": null}matches missing fields too, so there's nothing to do.
3. Generate the migration¶
$ mongomig revision --autogenerate -m "add status and plan"
Detected:
USERS
+ status: string = 'active' REQUIRES_DATA_MIGRATION backfill existing documents with 'active'
+ plan: string | null = None SAFE defaults to None: existing documents need no backfill
1 REQUIRES_DATA_MIGRATION · 1 SAFE
Generated e4f1c38b9d65 → migrations/versions/20261003_1851_e4f1c38b9d65_add_status_and_plan.py
updated: migrations/schema_snapshot.json
Review the file, then run `mongomig upgrade`.
The generated file (only the functions are shown; the docstring lists the changes):
def upgrade(ctx):
# status: new required field; backfill existing documents
ctx.ops.backfill("users", {"status": {"$exists": False}}, {"$set": {"status": "active"}})
def downgrade(ctx):
ctx.ops.unset_field("users", "status")
4. Check the impact on real data, then apply¶
$ mongomig plan
Migration plan for shop
4e3c7332253a initial schema applied
e4f1c38b9d65 add status and plan pending
e4f1c38b9d65 add status and plan Risk: LOW
users backfill $set status ~50,000 docs · collection scan
reversible: yes · deletes data: no · resumable: yes (checkpointed)
1 migration(s) · ~50,000 document writes · highest risk LOW
Estimates only; nothing was changed.
$ mongomig upgrade
Running upgrade 4e3c7332253a -> e4f1c38b9d65, add status and plan
• backfill users: 50,000 modified (50,000 matched, 50 batches)
✓ done in 788ms
Applied 1 revision(s).
$ mongomig current
Database: shop
Current: e4f1c38b9d65 add status and plan
Pending: none — up to date
Tip
Commit the revision file and migrations/schema_snapshot.json together. CI runs
mongomig validate, which fails if a model change has no migration.