Filter Expressions
The filter parameter on GraphQL queries accepts a Lucene query string. The system parses the query and translates it into LINQ expressions that are executed against the database.
Basic Syntax
filter: "fieldName:value"
Field names are case-insensitive and support dot-notation for nested properties.
Operators
Exact Match
filter: "status:Active"
filter: "orderId:12345"
Negation
Prefix with NOT or - to negate:
filter: "NOT status:Active"
filter: "-status:Active"
Wildcard Search
Use * for pattern matching (translates to SQL ILIKE):
filter: "name:*express*" # contains
filter: "name:Ship*" # starts with
filter: "name:*Ltd" # ends with
Wildcards only apply to string fields and custom values. For non-string simple types (int, bool, etc.), wildcards are automatically stripped and an exact match is performed instead.
Exists / Not Null
Use * as the value to check that a field is not null:
filter: "deliveryDate:*" # deliveryDate IS NOT NULL
filter: "-deliveryDate:*" # deliveryDate IS NULL
NULL Check
Use NULL as the value to match null fields:
filter: "deliveryDate:NULL" # deliveryDate IS NULL
filter: "-deliveryDate:NULL" # deliveryDate IS NOT NULL
Range Queries
Use bracket syntax for ranges:
filter: "created:[2024-01-01 TO 2024-12-31]" # inclusive both ends
filter: "created:{2024-01-01 TO 2024-12-31}" # exclusive both ends
filter: "amount:[100 TO *]" # >= 100
filter: "amount:[* TO 500]" # <= 500
Boolean Logic
Combine conditions with AND, OR, and grouping:
filter: "status:Active AND priority:High"
filter: "status:Active OR status:Pending"
filter: "(status:Active OR status:Pending) AND type:Import"
The default operator between terms is AND.
Nested Properties
Use dot notation to filter by nested object properties:
filter: "contact.name:Acme*"
filter: "route.origin.code:LAX"
Collection Properties
When filtering on a collection property, the system generates an Any() expression:
filter: "commodities.description:*electronics*"
This translates to: x.Commodities.Any(c => c.Description.Contains("electronics")).
Filtered Collections
Use bracket syntax to filter within a specific subset of a collection:
filter: "charges[chargeType:Freight].amount:[100 TO *]"
This translates to:
x.Charges.Where(c => c.ChargeType == "Freight").Any(c => c.Amount >= 100)
Bracket filters work with all filter operators, including range queries:
filter: "events[type:Departure].eventDate:[2024-01-01 TO 2024-12-31]"
filter: "children[category:Import].priority:[1 TO 10]"
When multiple bracket filters target the same collection in a single query, each filter is scoped independently.
Custom Value Filtering
Filter by custom field values stored in the customValues JSONB column:
filter: "customValues.invoiceNumber:INV*"
filter: "customValues.carrierId:123"
filter: "customValues.pickUpDate:NULL"
Custom Value NULL Behavior
Filtering customValues.field:NULL checks three conditions:
- The key does not exist in the dictionary
- The key exists but the value is
null - The key exists but the value is an empty string
All three conditions are treated as "null" for filtering purposes.
Join Filter Syntax
Filter by a property on a related entity referenced through a custom value foreign key. See Join Expressions for full details.
filter: "customValues.carrierId->contact.name:Acme*"
This builds a correlated subquery that joins to the Contacts table through the carrierId custom value.
Business Date Math
Filter expressions support business date math tokens when an IBusinessDateMathResolver is available:
| Token | Description |
|---|---|
BHOUR | Business hour calculation |
BDAY | Business day calculation |
filter: "dueDate:[now-2BDAY TO now]"
Business date math accounts for the organization's configured business hours and holidays.
GraphQL Usage
query {
orders(
organizationId: 1
filter: "status:Active AND customValues.priority:High"
orderBy: "-created"
limit: 25
) {
items {
orderId
status
customValues
}
totalCount
}
}
Related Topics
- Sorting Expressions - Dynamic sort syntax
- Join Expressions - Sort and filter by related entities
- Custom Fields - Custom value storage and naming