Mutations
DDO: Mutations and Updates
Mutations provide a powerful and declarative way to transform and update JSON data structures. This query language allows you to express complex transformations with a clean, readable format that is both expressive and concise.
Mutations are particularly useful for:
- Updating and transforming nested data structures
- Building workflows and automation pipelines
- Creating dynamic data processing systems
- Maintaining consistency in complex data updates
- Implementing business rules in a declarative way
- Building templating and document generation systems
Core Concepts
The Mutations DDO offers a system for modifying nested data structures through two main mechanisms:
- Mutation Operators - Operations that modify data at specific paths (prefixed with
$
) - Helper Functions - Template-based transformations that can be used within string values (prefixed with
@
)
These two approaches can be combined to create sophisticated data transformations with minimal code.
Operators
Operators in Mutations are special modifiers that define how a field's value should be transformed or updated. They provide a way to express transformations beyond simple assignments, enabling a wide range of data manipulation capabilities:
- Basic operators (
$set
,$incr
,$decr
, etc.) perform fundamental data modifications - List operators (
$add
,$remove
,$append
, etc.) manipulate array/list structures - ID operators (
$uuid
,$uuid4
,$uuid7
) generate unique identifiers - Time operators (
$now
,$formatdate
) handle date and time values - Special operators (
$template
,$rename
,$copy
, etc.) perform advanced transformations
Operators are always prefixed with a dollar sign ($
) and attached to field names with a colon, like field:$operator
. This consistent syntax makes mutations powerful yet readable, enabling complex transformations to be expressed in a clear, declarative format.
Query Syntax
Mutations support two syntax styles for specifying field paths: flat and nested.
Flat Syntax (With Dot Notation)
{
"field:$operator": value,
"nested.path.to.field:$operator": value
}
Where:
field
is the property name to update (can use dot notation for nested fields)$operator
is one of the supported mutation operatorsvalue
is the transformation value
For simple set operations, you can use the shorthand:
{
"field": value, # Equivalent to "field:$set": value
"nested.path.to.field": value
}
Nested Syntax (With Nested Dictionaries)
You can also use nested dictionaries to represent paths:
{
"parent": {
"child": {
"grandchild:$operator": value
}
}
}
This is equivalent to the flat syntax:
{
"parent.child.grandchild:$operator": value
}
Important: This syntax supports nesting for field paths only. The operator is always attached to the field name with a colon, not as a separate nested object.
Path Formats
The Mutations API supports three different ways to specify paths to the data you want to modify:
Dot Notation
Dot notation is the standard way to access nested properties. Each segment in the path represents a level in the object hierarchy:
{
"user.name:$set": "John Smith",
"user.preferences.theme:$set": "dark"
}
Array Indexing
Array indexing allows you to access and modify specific elements in arrays using square bracket notation:
{
"users[0].name:$set": "Alice",
"products[2].price:$incr": 10,
"orders[1].items[0].quantity:$decr": 1
}
JMESPath Queries
For advanced data access patterns, you can use JMESPath expressions prefixed with a question mark to filter and update multiple items at once:
{
"?products[?price > 100].category:$set": "premium",
"?users[?age < 18].accessLevel:$set": "restricted"
}
Basic Operations
$set
- Set Value
Set a field to a specific value, creating the field if it doesn't exist.
# Set user's name
{
"user.name:$set": "John Doe"
}
# Set multiple fields
{
"user.name:$set": "John Doe",
"user.email:$set": "john@example.com",
"user.status:$set": "active"
}
# Set nested values
{
"user.profile.bio:$set": "Software developer",
"user.settings.theme:$set": "dark"
}
$replace
- Replace Value
Replace an entire object or value with a new one.
# Replace entire user profile
{
"user.profile:$replace": {
"firstName": "John",
"lastName": "Doe",
"age": 30
}
}
# Replace array completely
{
"user.tags:$replace": ["premium", "verified"]
}
Numeric Operations
$incr
- Increment
Increase a numeric value by a specified amount.
# Increment user's score by 10
{
"user.score:$incr": 10
}
# Increment login count by 1
{
"user.loginCount:$incr": 1
}
# Increment with negative value (same as decrement)
{
"user.attempts:$incr": -1
}
# Increment multiple fields
{
"stats.views:$incr": 1,
"stats.totalTime:$incr": 120
}
$decr
- Decrement
Decrease a numeric value by a specified amount.
# Decrease user's credits by 5
{
"user.credits:$decr": 5
}
# Decrease inventory count
{
"product.inventory:$decr": 1
}
# Decrease multiple counters
{
"user.attemptsLeft:$decr": 1,
"user.credits:$decr": 10
}
Date and Time Operations
$datetime
- Set DateTime
Set a field to the current datetime or a shifted datetime.
# Set current datetime
{
"user.lastLogin:$datetime": True
}
# Set shifted datetime
{
"subscription.expiresAt:$datetime": "+30days"
}
# Multiple datetime operations
{
"order.createdAt:$datetime": True,
"order.estimatedDelivery:$datetime": "+3days"
}
# Supported shift formats:
# "+1day", "-2hours", "+30minutes", "+1year", "+6months"
$timestamp
- Set Timestamp
Set a field to the current Unix timestamp.
# Set current timestamp
{
"user.lastSeenTimestamp:$timestamp": True
}
# Multiple timestamp fields
{
"event.startTime:$timestamp": True,
"event.recordedAt:$timestamp": True
}
ID Generation
$uuid
- Generate UUID (No Dashes)
Generate a UUID without dashes.
# Generate user ID
{
"user.id:$uuid": True
}
# Generate session ID
{
"session.id:$uuid": True
}
$uuid4
- Generate UUID4 (With Dashes)
Generate a standard UUID4 with dashes.
# Generate order ID
{
"order.id:$uuid4": True
}
# Generate tracking ID
{
"shipment.trackingId:$uuid4": True
}
$uuid7
- Generate UUID7
Generate a time-ordered UUID7.
# Generate time-ordered ID
{
"document.id:$uuid7": True
}
Data Manipulation
$copy
- Copy Value
Copy a value from one field to another.
# Copy email to backup field
{
"user.email:$copy": "user.backupEmail"
}
# Copy billing address to shipping address
{
"billing.address:$copy": "shipping.address"
}
$rename
- Move/Rename Field
Move a value from one field to another (removes original).
# Rename field
{
"user.firstName:$rename": "user.name.first"
}
# Move field to new location
{
"tempData:$rename": "processedData"
}
$template
- Render Template
Render a template string with dynamic values.
# Create full name from parts
{
"user.fullName:$template": "{{ user.firstName }} {{ user.lastName }}"
}
# Create display text
{
"user.displayText:$template": "{{ user.name }} ({{ user.email }})"
}
# Create URL slug
{
"article.slug:$template": "{{ @slugify(article.title) }}"
}
Array Operations
$add
- Add to Array (If Not Present)
Add an item to an array only if it doesn't already exist.
# Add tag to user
{
"user.tags:$add": "premium"
}
# Add permission to role
{
"role.permissions:$add": "admin_access"
}
$addmulti
- Add Multiple Items
Add multiple items to an array (only if they don't exist).
# Add multiple tags
{
"user.tags:$addmulti": ["premium", "verified", "trusted"]
}
# Add multiple permissions
{
"role.permissions:$addmulti": ["read", "write", "delete"]
}
$remove
- Remove from Array
Remove specific items from an array.
# Remove tag from user
{
"user.tags:$remove": "trial"
}
# Remove permission
{
"role.permissions:$remove": "temp_access"
}
$removemulti
- Remove Multiple Items
Remove multiple items from an array.
# Remove multiple tags
{
"user.tags:$removemulti": ["trial", "temporary"]
}
# Remove multiple permissions
{
"role.permissions:$removemulti": ["temp_read", "temp_write"]
}
$append
- Add to End of Array
Add an item to the end of an array (always adds, even if duplicate).
# Add log entry
{
"user.loginHistory:$append": {
"timestamp": "2024-01-15T10:30:00Z",
"ip": "192.168.1.1"
}
}
# Add item to cart
{
"cart.items:$append": {
"productId": "prod_123",
"quantity": 2
}
}
$appendfirst
- Add to Beginning of Array
Add an item to the beginning of an array.
# Add recent activity to top
{
"user.recentActivities:$appendfirst": {
"action": "login",
"timestamp": "2024-01-15T10:30:00Z"
}
}
$pop
- Remove from End
Remove and return the last item from an array.
# Remove last item from queue
{
"queue.items:$pop": True
}
$popfirst
- Remove from Beginning
Remove and return the first item from an array.
# Process first item in queue
{
"queue.pending:$popfirst": True
}
Advanced Mutations with JMESPath
Apply mutations to multiple documents using JMESPath filtering.
# Add permission to all admin users
{
"users[?role == 'admin'].permissions:$add": "super_admin"
}
# Increment view count for all published articles
{
"articles[?status == 'published'].viewCount:$incr": 1
}
# Set expiry date for all trial subscriptions
{
"subscriptions[?type == 'trial'].expiresAt:$datetime": "+7days"
}
# Update priority for all urgent orders
{
"orders[?priority == 'urgent'].status:$set": "processing"
}
Expression-Based Mutations
Use template expressions for dynamic mutations.
# Set full name using expression
{
"&user.fullName": "user.firstName + ' ' + user.lastName"
}
# Calculate total with tax
{
"&order.totalWithTax": "order.subtotal * 1.08"
}
# Set status based on condition
{
"user.status:$template": "{{ @if_else(user.age >= 18, 'adult', 'minor') }}"
}
# Generate display name
{
"&user.displayName": "@coalesce(user.nickname, user.firstName)"
}
Complex Mutation Examples
# User registration complete
{
"user.status:$set": "active",
"user.registeredAt:$datetime": True,
"user.id:$uuid4": True,
"user.tags:$add": "new_user",
"user.loginCount:$set": 0,
"user.profile.completionScore:$set": 100
}
# Order processing
{
"order.status:$set": "processing",
"order.processedAt:$datetime": True,
"order.items[*].status:$set": "allocated",
"order.tracking.events:$append": {
"event": "processing_started",
"timestamp": "{{ @now() }}"
}
}
# Bulk user permissions update
{
"users[?department == 'engineering'].permissions:$addmulti": ["code_review", "deploy"],
"users[?role == 'senior'].permissions:$add": "mentor",
"users[?status == 'inactive'].permissions:$set": []
}