Skip to main content

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:

  1. Mutation Operators - Operations that modify data at specific paths (prefixed with $)
  2. 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 operators
  • value 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": []
}