Skip to content

Pydongo Mutation System Guide

Updates from Mutations

Pydongo's mutation system allows you to perform atomic MongoDB updates on large numbers of documents without loading them into memory.

Instead of fetching documents, modifying them in Python, and saving them one by one (which becomes slow and memory-intensive for thousands or millions of records), you can compose MongoDB update operations directly using familiar Python syntax.

This is the primary intended use case of the Mutation DSL.

Core Idea

  • Write Python-like syntax -> Generate efficient MongoDB bulk/atomic updates
  • No documents are loaded into memory when using collection-level mutations

Example

# Efficient: updates 10,000+ documents in one MongoDB operation
query = users.find(users.followers < 50)
query.followers += 10
query.posts.add_to_set(Post(content="Thanks for being active!"))
query.mutate()               # Single updateMany() call

How to Create and Apply Mutations

Mutations are collected automatically inside a context created when you call .find().

query = collection.find(collection.age > 30)

# These statements build mutations in the shared context
query.status = "active"                    # $set
query.score += 100                         # $inc
query.tags.add_to_set("vip")               # $addToSet
query.profile.views.setmax(1000)           # $max
query.bio.unset()                          # $unset

# Execute the bulk update (updateMany)
result = query.mutate()                    # or await query.amutate()

You can always inspect the generated update document:

print(query.get_mutations())
# {
#   "$set": {"status": "active"},
#   "$inc": {"score": 100},
#   "$addToSet": {"tags": "vip"},
#   "$max": {"profile.views": 1000},
#   "$unset": {"bio": ""}
# }

Supported Mutation Operations

Python Syntax MongoDB Operator Example / Notes
field = value $set user.name = "Alice"
field.unset() $unset Removes field completely
numeric += n / numeric -= n $inc followers += 10, balance -= 50
numeric *= n $mul score *= 1.5
numeric /= n $mul (1/n) price /= 2
field.setmax(value) $max Keeps greater value
field.setmin(value) $min Keeps smaller value
array.push(value) $push Append value
array.add_to_set(value) $addToSet Add only if not present
array.pull(value) $pull Remove matching values
array.popleft() $pop: 1 Remove first element
array.popright() $pop: -1 Remove last element
nested.field = value dot notation user.address.city = "Paris"

Single Document Updates (less common use case)

For single documents, modifying the Python object and calling .save() is usually more readable.

The real power of the Mutation DSL appears when performing bulk updates without fetching documents.

When to Use Which Approach

Goal Recommended Approach Memory Usage Speed (large N)
Update 1 document (already loaded) Modify object -> .save() Low -
Update hundreds / thousands / millions .find(...).mutate() None Very fast
Complex per-document logic Load -> process -> save (loop) High Slow

Pydongo's Mutation DSL lets you harness MongoDB's atomic updateMany power using clean, type-safe Python syntax.

Perfect for bulk maintenance tasks, counter updates, user rewards, data cleanups, and migrations.

See the social_media_app.py example for a complete demonstration of rewarding many users in a single operation.