Skip to main content
Filters allow you to select specific items from arrays based on conditions. Using the ?() operator, you can query data, perform conditional selection, and extract exactly what you need.
Filters are a standard JSONPath feature that enables SQL-like querying of JSON data structures.

Filter Syntax

Filters use the ?() operator with conditional expressions:
$.array[?(expression)]
  • ? - Indicates a filter operation
  • (expression) - The condition to evaluate
  • @ - References the current item being filtered
{
  "activeUsers": "$.users[?(@.active===true)]"
}
Filters always return an array, even if only one item matches. To get a single item, you can combine with array indexing: $.users[?(@.active===true)][0]

The @ Symbol

Inside filter expressions, @ represents the current item being evaluated.
Filter
{
  "expensiveItems": "$.products[?(@.price>100)]"
}
Data
{
  "products": [
    {"name": "Widget", "price": 29.99},
    {"name": "Gadget", "price": 149.99},
    {"name": "Doohickey", "price": 199.99}
  ]
}
Result
{
  "expensiveItems": [
    {"name": "Gadget", "price": 149.99},
    {"name": "Doohickey", "price": 199.99}
  ]
}
@ refers to each product object as it’s evaluated.

Comparison Operators

Use JavaScript comparison operators in filter expressions:
Filters
{
  "admins": "$.users[?(@.role===admin)]",
  "notAdmins": "$.users[?(@.role!==admin)]",
  "active": "$.users[?(@.active===true)]",
  "inactive": "$.users[?(@.active===false)]"
}
Operators:
  • === - Strict equality (recommended)
  • !== - Strict inequality
  • == - Loose equality
  • != - Loose inequality

Comparison Operators Reference

OperatorDescriptionExample
===Strict equal?(@.status===active)
!==Strict not equal?(@.status!==deleted)
==Loose equal?(@.count==5)
!=Loose not equal?(@.count!=0)
>Greater than?(@.price>100)
<Less than?(@.age<18)
>=Greater or equal?(@.score>=80)
<=Less or equal?(@.quantity<=10)
Use === (strict equality) instead of == to avoid type coercion issues. For example, 5 == "5" is true, but 5 === "5" is false.

Logical Operators

Combine multiple conditions with logical operators:
Filter
{
  "premiumActive": "$.users[?(@.tier===premium && @.active===true)]"
}
Data
{
  "users": [
    {"name": "Alice", "tier": "premium", "active": true},
    {"name": "Bob", "tier": "premium", "active": false},
    {"name": "Charlie", "tier": "basic", "active": true}
  ]
}
Result
{
  "premiumActive": [
    {"name": "Alice", "tier": "premium", "active": true}
  ]
}
Both conditions must be true.

Advanced Filter Variables

JSONPath Plus provides special variables for accessing related data:
Access the root document from within a filter:
Filter
{
  "matchingOrders": "$.orders[?(@[email protected]_id)]"
}
Data
{
  "trigger": {
    "customer_id": "CUST-123"
  },
  "orders": [
    {"id": "ORD-1", "customerId": "CUST-123"},
    {"id": "ORD-2", "customerId": "CUST-456"},
    {"id": "ORD-3", "customerId": "CUST-123"}
  ]
}
Result
{
  "matchingOrders": [
    {"id": "ORD-1", "customerId": "CUST-123"},
    {"id": "ORD-3", "customerId": "CUST-123"}
  ]
}
@root lets you compare array items against trigger data or other nodes.

Filter Variables Reference

VariableDescriptionExample
@Current item?(@.price>10)
@.propertyItem’s property?(@.active===true)
@rootRoot document?(@[email protected])
@parentParent object?(@parent.category===premium)
@propertyProperty name/index?(@property!==0)
@parentPropertyParent’s property name?(@parentProperty!==hidden)
@pathJSONPath to item?(@path!==\"$[0]\")

Type Selectors in Filters

Filter by data type using type selector operators:
Filters
{
  "stringValues": "$.data[*][?(@string())]",
  "numberValues": "$.data[*][?(@number())]",
  "booleanValues": "$.data[*][?(@boolean())]"
}
Data
{
  "data": [
    {"value": "text"},
    {"value": 42},
    {"value": true},
    {"value": "another string"}
  ]
}
Select items by their type.

Type Selectors Reference

SelectorMatchesExample
@string()String values?(@string())
@number()All numbers?(@number())
@integer()Integer numbers only?(@integer())
@boolean()true or false?(@boolean())
@array()Arrays?(@array())
@object()Objects?(@object())
@null()null values?(@null())
@scalar()Non-object/non-function?(@scalar())

Complex Filter Patterns

Filter
{
  "midRange": "$.products[?(@.price>=50 && @.price<=150)]"
}
Select items within a numeric range.

Real-World Examples

Filters
{
  "recentOrders": "$.orders[?(@.total>100 && @.status===completed)]",
  "pendingHighValue": "$.orders[?(@.status===pending && @.total>500)]",
  "freeShipping": "$.orders[?(@.total>=50)]",
  "needsReview": "$.orders[?(@.total>1000 && @.verified===false)]"
}
Common e-commerce filtering patterns.

Combining Filters with Other Operations

Mapping
{
  "firstActive": "$.users[?(@.active===true)][0]",
  "lastPremium": "$.users[?(@.tier===premium)][-1]"
}
Get a single item from filtered results.

Common Pitfalls

Wrong:
"$.users[?(@.role=admin)]"  // ❌ Single = is assignment, not comparison
Correct:
"$.users[?(@.role===admin)]"  // ✅ Use === for comparison
Wrong:
"$.users[?(@.status===active)]"  // ❌ Missing quotes around 'active'
Correct:
"$.users[?(@.status==='active')]"  // ✅ Strings need quotes
Note: In some implementations, quotes are optional, but it’s best practice to include them.
Issue:
{"user": "$.users[?(@.id===123)]"}  // Returns array, not single object
Solution:
{"user": "$.users[?(@.id===123)][0]"}  // Add [0] to get first item
Issue:
"$.users[?(@.middleName===Smith)]"  // What if middleName doesn't exist?
Better:
"$.users[?(@.middleName && @.middleName===Smith)]"  // Check existence first

Performance Considerations

Efficient Filters

// ✅ Simple conditions
"$.users[?(@.active===true)]"

// ✅ Direct property checks
"$.items[?(@.price>100)]"

Slower Filters

// ⚠️ Complex nested filters
"$.data[?(@.nested[?(@.x>5)])]"

// ⚠️ Many conditions
"$.items[?(@.a && @.b && @.c && @.d)]"
Optimization tips:
  • Filter early in your JSONPath expression to reduce data being processed
  • Use simple conditions when possible
  • Consider splitting complex filters into multiple steps
  • Test with realistic data sizes

Building Complex Filters

1

Start Simple

Begin with a basic filter:
{"filtered": "$.items[?(@.price>10)]"}
2

Add One Condition

Add conditions incrementally:
{"filtered": "$.items[?(@.price>10 && @.active===true)]"}
3

Test Each Addition

Verify the filter works after each change using the Flow Debugger
4

Use Parentheses for Complex Logic

Group conditions clearly:
{"filtered": "$.items[?(@.price>10 && (@.category===A || @.category===B))]"}
5

Consider Readability

If the filter becomes too complex, consider:
  • Breaking into multiple filters
  • Using separate nodes for each filter step
  • Adding comments in your flow documentation

Quick Reference

$.array[?(expression)]
  • Always returns an array
  • Use @ for current item
  • Combine with [0] for single item
===  !==  ==  !=  >  <  >=  <=
Prefer === over == for type safety
&&  (AND)
||  (OR)
Use parentheses for complex logic
@           Current item
@root       Root document
@parent     Parent object
@property   Property name/index
@path       JSONPath to item

What’s Next?

Questions? Check the Reference or visit our Help Center.