Querying
DDO: Querying
Querying in DDO uses comparison and logical operators to find documents that match specific criteria.
Querying are particularly useful for:
- Filtering lists of objects/dictionaries
 - Searching through complex nested data structures
 - Building dynamic query interfaces
 - Creating data pipelines with filtering stages
 - Simplifying data retrieval logic in applications
 
Query Syntax
Filters 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:
fieldis the property name to filter on (can use dot notation for nested fields)$operatoris one of the supported filter operatorsvalueis the comparison value to filter against
For simple equality checks, you can use the shorthand:
{
    "field": value,  # Equivalent to "field:$eq": 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.
Example Testing Nested Structure
Let's look at an example that demonstrates filtering with a deeply nested structure:
# Sample data
data = [
    {
        "name": {
            "deep": {
                "datalength": 3,
                "values": ["a", "b", "c"]
            }
        },
        "status": "active"
    },
    {
        "name": {
            "deep": {
                "datalength": 7,
                "values": ["a", "b", "c", "d", "e", "f", "g"]
            }
        },
        "status": "pending"
    },
    {
        "name": {
            "deep": {
                "datalength": 2,
                "values": ["x", "y"]
            }
        },
        "status": "active"
    }
]
# Using flat syntax
flat_filter = {
    "name.deep.datalength:$gt": 5
}
# Using nested syntax
nested_filter = {
    "name": {
        "deep": {
            "datalength:$gt": 5
        }
    }
}
# Both filters will return the same item (the second one with datalength 7)
This example shows how both syntaxes target the same nested data effectively.
Basic Comparison Operators
$eq - Equal To
Find documents where a field equals a specific value.
# Find users named "John"
{
    "name:$eq": "John"
}
# Alternative shorthand (implicit $eq)
{
    "name": "John"
}
# Find users with exactly 5 login attempts
{
    "loginAttempts:$eq": 5
}
$ne - Not Equal To
Find documents where a field does not equal a specific value.
# Find users who are not banned
{
    "status:$ne": "banned"
}
# Find products that aren't out of stock
{
    "inventory.quantity:$ne": 0
}
$gt - Greater Than
Find documents where a field is greater than a value.
# Find users older than 25
{
    "age:$gt": 25
}
# Find orders with value greater than $100
{
    "total:$gt": 100.00
}
$gte - Greater Than or Equal
Find documents where a field is greater than or equal to a value.
# Find users 18 or older
{
    "age:$gte": 18
}
# Find high-priority items (priority 7 or above)
{
    "priority:$gte": 7
}
$lt - Less Than
Find documents where a field is less than a value.
# Find junior employees (less than 2 years experience)
{
    "experience:$lt": 2
}
# Find small orders (less than $50)
{
    "total:$lt": 50.00
}
$lte - Less Than or Equal
Find documents where a field is less than or equal to a value.
# Find users 65 or younger
{
    "age:$lte": 65
}
# Find budget items ($25 or less)
{
    "price:$lte": 25.00
}
Array and Collection Operators
$in - Value In Array
Find documents where a field's value is in a specified array.
# Find users with specific roles
{
    "role:$in": ["admin", "moderator", "editor"]
}
# Find products in certain categories
{
    "category:$in": ["electronics", "computers", "mobile"]
}
$nin - Value Not In Array
Find documents where a field's value is not in a specified array.
# Find users who are not in restricted roles
{
    "role:$nin": ["banned", "suspended", "deleted"]
}
# Find products not in discontinued categories
{
    "category:$nin": ["discontinued", "obsolete"]
}
$all - All Values Match
Find documents where an array field contains all specified values.
# Find users with all required permissions
{
    "permissions:$all": ["read", "write", "delete"]
}
# Find products with all required tags
{
    "tags:$all": ["featured", "bestseller"]
}
$size - Array Size
Find documents where an array has a specific length.
# Find users with exactly 3 skills
{
    "skills:$size": 3
}
# Find orders with exactly 2 items
{
    "items:$size": 2
}
String Operators
$contains - Contains Substring
Find documents where a string field contains a substring.
# Find users with "gmail" in their email
{
    "email:$contains": "gmail"
}
# Find products with "wireless" in description
{
    "description:$contains": "wireless"
}
$startswith - Starts With
Find documents where a string field starts with a prefix.
# Find users with names starting with "John"
{
    "name:$startswith": "John"
}
# Find phone numbers starting with country code
{
    "phone:$startswith": "+1"
}
$endswith - Ends With
Find documents where a string field ends with a suffix.
# Find files with .pdf extension
{
    "filename:$endswith": ".pdf"
}
# Find email addresses from specific domain
{
    "email:$endswith": "@company.com"
}
Pattern Matching
$match - Pattern Matching
Find documents using wildcard patterns or regex.
# Wildcard patterns (* for multiple chars, ? for single char)
{
    "filename:$match": "report_*.pdf"
}
# Find names with specific pattern
{
    "code:$match": "PRD-????-2023"
}
# Regex patterns (enclosed in forward slashes)
{
    "email:$match": "/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/"
}
$regex - Regular Expression
Find documents using regular expressions.
# Find phone numbers in specific format
{
    "phone:$regex": "^\\+1-\\d{3}-\\d{3}-\\d{4}$"
}
# Find postal codes
{
    "zipcode:$regex": "^\\d{5}(-\\d{4})?$"
}
Existence and Type Checking
$exists - Field Exists
Find documents where a field exists or doesn't exist.
# Find users with a profile picture
{
    "profilePicture:$exists": True
}
# Find users without a middle name
{
    "middleName:$exists": False
}
$type - Type Checking
Find documents where a field is of a specific type.
# Find documents where age is a number
{
    "age:$type": "number"
}
# Find documents where tags is an array
{
    "tags:$type": "array"
}
# Supported types: string, number, boolean, array, object, null
Complex Filtering with JMESPath
DDO supports JMESPath expressions for complex filtering scenarios.
# Find admin users
{
    "users[?role == 'admin'].name": "*"
}
# Find active orders over $100
{
    "orders[?status == 'active' && total > 100].id": "*"
}
# Find users in specific age range
{
    "users[?age >= 25 && age <= 65].email": "*"
}
Combining Filters
You can combine multiple filter conditions in a single QLO:
# Find active adult users with gmail accounts
{
    "status": "active",
    "age:$gte": 18,
    "email:$contains": "gmail"
}
# Find premium products in stock within price range
{
    "category": "premium",
    "stock:$gt": 0,
    "price:$gte": 100,
    "price:$lte": 500
}