Skip to main content

Data Directive Object: DDO

Singlebase provides a modern, unified Data Directive Object (DDO) language inspired by MongoDB but designed for clarity and comprehensive functionality across your entire application stack.

What is DDO?

DDO (Data Directive Object) is a powerful, intuitive unified language dictionary for modern applications. It combines the familiar concepts of MongoDB with a streamlined syntax that makes complex operations simple and readable across multiple domains.

DDO uses a core data structure - a simple dictionary/JSON that describes what you want to do across your application. Whether you're querying and mutating document-based databases, handling authentication, managing file uploads, performing vector database operations, integrating AI services, or executing other application functions, you express your intentions through these structured objects that form the foundation of all DDO operations.

This unified approach means you learn one language dictionary that works consistently across database queries, user authentication flows, file management, AI integrations, vector searches, and beyond - eliminating the need to master multiple APIs and syntax patterns for different parts of your application.

DDO uses simple dictionary structures that describe what you want to do with your data. Every request is a DDO containing an op field that specifies the operation:

Example of DDO

{
"op": "collection.find", // The operation to perform
"collection": "users", // Operation-specific parameters
"match": { "status": "active" },
"limit": 10
}

DDO Benefits:

  • Consistent: Same request format across all APIs
  • Simple: Plain JSON objects, no complex query syntax
  • Powerful: Supports complex filtering with operators like $gt, $in, $regex
  • Familiar: Similar to MongoDB query syntax but streamlined

Some Syntax with DDO

# Filtering QLO - operators in the key
filter_ddo = {
"user.age:$gte": 18, # age greater than or equal to 18
"user.status:$eq": "active", # status equals "active"
"user.name:$contains": "John" # name contains "John"
}

# Mutation DDO - operators in the key
update_ddo = {
"user.lastLogin:$datetime": True, # set current datetime
"user.loginCount:$incr": 1, # increment by 1
"user.tags:$add": "premium" # add tag if not exists
}

# Projection DDO - no operators, uses templates
projection_ddo = {
"fullName": "{{ user.firstName }} {{ user.lastName }}",
"age": "?{{ user.age }}",
"&isAdult": "user.age >= 18"
}

Core Concepts

Path Notation

DDO uses dot notation to navigate nested documents:

  • "user.name" - Access the name field in the user object
  • "users[0].email" - Access the email of the first user in an array
  • "orders[?status=='pending'].total" - JMESPath query for filtering

Expression Syntax

DDO supports multiple expression formats:

  • "{{ expression }}" - Template expressions (returns string)
  • "?{{ expression }}" - Native expressions (returns original data type)
  • "&field" - Shorthand for simple expressions

Operator Syntax

DDO operators are placed in the key of the property using the :$


Best Practices

Query Optimization

  • Use specific field names rather than wildcards when possible
  • Combine multiple conditions in a single QLO rather than multiple queries
  • Use $exists: false instead of $eq: null for better performance

Mutation Safety

  • Always validate data types before applying numeric operations ($incr, $decr)
  • Use $add instead of $append for arrays to avoid duplicates
  • Use templates for complex string operations rather than multiple mutations

Error Handling

  • DDO provides detailed error messages for invalid paths and operations
  • Use $exists checks before applying operations to optional fields
  • Validate array operations to ensure the target field is actually an array

Common Use Cases

User Management

# User login tracking
{
"user.lastLogin:$datetime": True,
"user.loginCount:$incr": 1,
"user.loginHistory:$append": {
"timestamp": "{{ @now() }}",
"ip": "{{ request.ip }}"
}
}

E-commerce Operations

# Add item to cart
{
"cart.items:$append": {
"productId": "{{ product.id }}",
"quantity": 1,
"price": "{{ product.price }}",
"addedAt": "{{ @now() }}"
},
"cart.itemCount:$incr": 1,
"cart.total:$incr": "{{ product.price }}"
}

Content Management

# Publish article
{
"article.status:$set": "published",
"article.publishedAt:$datetime": True,
"article.slug:$template": "{{ @slugify(article.title) }}",
"article.tags:$add": "featured"
}

.

& - Expression Shorthand

Prefix for field names to indicate shorthand expression syntax with native type preservation.

# Equivalent expressions:
{
"&count": "@length(items)", # Shorthand
"count": "?{{ @length(items) }}" # Full syntax
}

{
"&isActive": "status == 'active'", # Shorthand boolean
"isActive": "?{{ status == 'active' }}" # Full syntax
}

{
"&total": "price * quantity", # Shorthand calculation
"total": "?{{ price * quantity }}" # Full syntax
}

Usage: Use & prefix for concise expressions that should return native data types.

Template Expression Delimiters

{{ }} - String Template

Template expressions that always return string values, even if the inner expression evaluates to a different type.

{
"message": "Hello {{ user.name }}!", # String interpolation
"count": "{{ @length(items) }}", # Returns "5" (string)
"price": "{{ product.price }}", # Returns "29.99" (string)
"display": "Total: {{ @sum(values) }} items" # Mixed string/expression
}

Usage: Use for string interpolation and when you need string output regardless of expression type.

?{{ }} - Native Type Template

Template expressions that preserve the native data type of the evaluated expression.

{
"count": "?{{ @length(items) }}", # Returns 5 (number)
"isActive": "?{{ status == 'active' }}", # Returns true (boolean)
"data": "?{{ user.profile }}", # Returns object
"tags": "?{{ @split(tagString, ',') }}", # Returns array
"price": "?{{ product.price * 0.9 }}" # Returns 26.991 (number)
}

Usage: Use when you need the expression result in its native data type (number, boolean, object, array).

@ - Helper Function Prefix

Identifies template helper functions within expressions.

{
"timestamp": "{{ @now() }}", # Current datetime
"id": "{{ @uuid4() }}", # Generate UUID
"slug": "{{ @slugify(title) }}", # Convert to URL slug
"total": "?{{ @sum(@map(items, 'price')) }}", # Calculate sum
"greeting": "{{ @if_else(isAdmin, 'Admin', 'User') }}" # Conditional
}

Usage: All helper functions start with @. Can be used within any template expression type.

Projection Special Keys and Values

_ - Field Selection Key

Special key in projections used to control which fields from the source data are included.

# Include all fields
{
"_": "**",
"extraField": "{{ computed_value }}"
}

# Include specific fields only
{
"_": "{name, email, age}",
"displayName": "{{ name }}"
}

# Exclude specific fields
{
"_": "!{password, ssn, internal_notes}",
"publicId": "{{ @md5(user_id) }}"
}

Usage: Only used in projection QLOs. Controls field inclusion/exclusion from source data.

** - Include All Fields

Value used with the _ key to include all fields from the source data.

{
"_": "**" # Include every field from source
}

Usage: Use when you want to preserve all original data and add computed fields.

{field1, field2, ...} - Include Specific Fields

Value used with the _ key to include only specified fields from the source data.

{
"_": "{id, name, email, created_at}" # Only include these fields
}

Usage: Use for whitelisting specific fields, ideal for API responses and data sanitization.

!{field1, field2, ...} - Exclude Specific Fields

Value used with the _ key to exclude specified fields while including all others.

{
"_": "!{password, ssn, internal_id, secret_key}" # Exclude these fields
}

Usage: Use for blacklisting sensitive or internal fields while keeping everything else.

Syntax Examples by Category

Filtering Queries

{
"user.age:$gte": 18, # :$ operator syntax
"user.status:$eq": "active", # String equality
"user.tags:$contains": "premium", # String contains
"user.orders:$size": 5 # Array size
}

Mutations

{
"user.loginCount:$incr": 1, # :$ operator syntax
"user.lastSeen:$datetime": True, # Set current datetime
"user.tags:$add": "verified", # Add to array
"user.profile:$set": { "bio": "..." } # Set object value
}

Projections with Templates

{
# String templates
"greeting": "Hello {{ user.name }}!",

# Native type templates
"isAdult": "?{{ user.age >= 18 }}",

# Shorthand expressions
"&fullName": "user.firstName + ' ' + user.lastName",

# Helper functions
"formattedDate": "{{ @format_date(user.created, 'YYYY-MM-DD') }}",

# Field selection
"_": "!{password, ssn}",

# Mixed usage
"summary": "User {{ user.name }} has ?{{ @length(user.orders) }} orders"
}

Complex Expressions

{
# Nested helper functions
"&avgOrderValue": "@avg(@map(@filter(orders, 'status == \"completed\"'), 'total'))",

# Conditional with calculations
"discount": "?{{ @if_else(user.isPremium, price * 0.1, 0) }}",

# String formatting with helpers
"display": "{{ @titlecase(name) }} ({{ @format_date(created, 'MMM YYYY') }})",

# Multiple field operations
"_": "!{internal_notes, cost_basis}",
"&profit": "selling_price - cost_basis",
"status": "{{ @switch(inventory_count, {'0': 'Out of Stock', '>0': 'Available'}, 'Unknown') }}"
}

Best Practices for Syntax Usage

  1. Use & for simple expressions that need native types
  2. Use {{ }} for string formatting and display text
  3. Use ?{{ }} for calculations and data type preservation
  4. Use _ strategically in projections to control data exposure
  5. Combine syntax elements for powerful data transformations
  6. Use @ helpers to leverage built-in functionality rather than complex expressions

This glossary serves as a quick reference for all DDO syntax elements and their proper usage patterns.