Skip to content

Filters

Scribe supports four filter formats. It auto-detects which one you’re using, so pick whatever fits your context. If you’re deciding which format to use, see Choosing a Filter Format.

Filter Format Detection

Auto-detection order for filter syntax

Filters are detected in this order:

FormatDetectionBest for
JSONStarts with { or [Programmatic queries, SDKs
LDAPStarts with ( and ends with )Legacy systems, LDAP clients
FleXTried nextInteractive queries, config files
SCIMFallbackREST APIs, SCIM clients
OperationFleXJSONSCIMLDAP
Equalitycn = John{"cn": "John"}cn eq "John"(cn=John)
Not equalcn != John{"cn": {"ne": "John"}}cn ne "John"(!(cn=John))
Starts withcn ^= J{"cn": {"sw": "J"}}cn sw "J"(cn=J*)
Containscn %= oh{"cn": {"co": "oh"}}cn co "oh"(cn=*oh*)
Existscn?{"cn": {"pr": true}}cn pr(cn=*)
ANDa=1 b=2{"a": "1", "b": "2"}a eq "1" and b eq "2"(&(a=1)(b=2))
ORa=1 or b=2{"_or_": [...]}a eq "1" or b eq "2"(|(a=1)(b=2))
Attr groupa|b = x{"a|b": "x"}

All four formats work identically in REST and GraphQL queries.


Timestamp attributes (createTimestamp, modifyTimestamp, verifiedTimestamp) accept flexible temporal references instead of absolute timestamps. Works with all filter formats.

FormatExampleDescription
nowmodifyTimestamp ge nowCurrent time
now-durationmodifyTimestamp ge now-1h1 hour ago
now+durationverifiedTimestamp lt now+1d1 day from now
DurationcreateTimestamp ge 7d7 days ago
ISO durationmodifyTimestamp ge P30D30 days ago
Partial datecreateTimestamp ge 2024Start of 2024
Day keywordsmodifyTimestamp ge todayMidnight UTC
Period keywordscreateTimestamp ge this_weekStart of period
Relative periodsmodifyTimestamp ge last 3 daysN units ago

Day keywords: yesterday, today, tomorrow

Period keywords: this week, last week, this month, last month, this year, last year (Also: this_week, thisweek, last-month, etc.)

Relative periods: last N units where units can be days, hours, minutes, weeks, etc.


FleX (Flexible Filter Expressions) is a query language that reads like plain English. Values rarely need quoting, whitespace is lenient, and every operator has a natural-language form alongside short symbols and SCIM keywords.

# Reads like a sentence — no quotes, no special syntax
department is Engineering
name starts with John
modified after 2024-01-01
# Same queries, terse style
department=Engineering
name ^= John
modified > 2024-01-01
# Or use SCIM-style operator keywords
department eq Engineering
name sw John
modified gt 2024-01-01

Values like Engineering, John, numbers, dates, UUIDs, IPs, and durations (50ms, 5s) need no quoting. Quote only when a value contains spaces — backticks, single quotes, or double quotes all work: cn = `John Doe`.

# Combine with AND (implicit) and OR
department is Engineering status is active
role in (admin, editor) or department is Engineering
# Natural negation
status isnt disabled
name not starts with Test
role not in (guest, anonymous)
# Phonetic and pattern matching
sn sounds like Smith
cn like John*
mail ends with @example.com
OperatorAliasesDescription
=, ==eq, is, equalsEquality
!=, !==ne, isnt, is notNot equal
>gt, after, greater thanGreater than
>=ge, min, at leastGreater or equal
<lt, before, less thanLess than
<=le, max, at mostLess or equal
OperatorAliasesDescription
^=sw, starts with, prefixStarts with
$=ew, ends with, suffixEnds with
%=co, contains, hasContains substring
*=matches, like, globWildcard/glob pattern
~=approx, sounds like, similar toApproximate match (phonetic)
OperatorAliasesDescription
?exists, present, prAttribute exists
inone ofValue in set
not in!in, not one ofValue not in set

Whitespace between conditions implies AND. Use or, ,, |, or || for OR. AND binds tighter than OR — use parentheses to override:

# Implicit AND
result=ok duration<=50ms
# Explicit OR
result=ok or result=warn
# Parentheses override precedence
channel=LDAP (op=Search or op=Bind)

FleX treats is, not, and ! as modifier words you can drop in front of operators for more natural phrasing.

is is optional before comparison, set, presence, and approximate operators — it reads better but changes nothing:

count is at least 10 # same as: count >= 10
status is in (a, b, c) # same as: status in (a, b, c)
name is present # same as: name exists
name is similar to john # same as: name ~= john

Standalone is means equals: status is active is the same as status = active.

not and ! negate any operator:

result != ok
cn not starts with 'Test'
status not in (admin, root)
!(result = ok)
not(result = ok)

is not, isnt, isn't combine both — natural negation for the same operators is supports:

status isnt active # same as: status != active
count is not greater than 5 # same as: count <= 5
name isn't present # same as: name not exists

Simple values need no quotes. Use backticks, single quotes, or double quotes for values with spaces:

status = active
cn = `John Doe`

Special values: null and nil map to “not exists”; true and false are booleans. Quote them to match the literal string.

FleX recognizes unquoted numbers, hex (0xFF), durations (50ms, 5s), timestamps (2024-01-15), UUIDs, IPs, and emails.

Search across multiple attributes with a single condition. Exclusive to FleX and JSON — LDAP and SCIM require explicit OR clauses.

# Pipe syntax (no whitespace around |)
sn|givenName|cn|mail contains 'admin'
# Brace syntax (whitespace allowed)
{sn, givenName, cn, mail} contains 'admin'

Both expand to the same OR expression. Use pipe for compact inline filters; use braces for readability with many attributes.

status in (active, pending, review)
role not in (admin, superuser)

Empty sets check presence: status in () is equivalent to status exists, and status not in () is equivalent to status not exists.

For DN-based matching (LDAP :dn modifier):

member:dn := "cn=John,ou=users,dc=example,dc=com"
ou:dn := Engineering

FleX works in log filtering rules and HOCON config files too.


Structured, programmatic filters for SDKs and code generation.

// Simple equality
{"cn": "john"}
// Multiple conditions (AND)
{"cn": "john", "sn": "doe"}
// Array of values (OR)
{"cn": ["john", "jane"]}
// Operator with value
{"cn": {"sw": "A"}}
// Explicit logical operators
{"_or_": [{"cn": "a"}, {"cn": "b"}]}
{"_not_": {"disabled": "true"}}
  • Object {...}: Keys are combined with AND
  • Array [...]: Elements are combined with AND
OperatorAliasesMeaning
eqequals, is, =Equals
nenotEquals, !=Not equals
cocontains, %Contains substring
swstartsWith, ^Starts with
ewendsWith, $Ends with
prexistsAttribute present
gt>, afterGreater than
gegte, >=, minGreater or equal
lt<, beforeLess than
lelte, <=, maxLess or equal
approx~, soundsLikeApproximate match
matches*Wildcard pattern
includesin, oneOfValue in set
excludesnotIn, notOneOfValue not in set

Use _and_, _or_, and _not_ (or without underscores):

{"_or_": [{"status": "active"}, {"status": "pending"}]}
{"_not_": {"disabled": "true"}}
{"_and_": [
{"type": "user"},
{"_or_": [{"role": "admin"}, {"role": "operator"}]}
]}
JSON TypeResult
StringUsed as-is
NumberPlain string (no scientific notation)
Boolean"true" or "false"
NullTreated as “not exists”

Pipe syntax works identically to FleX:

{"sn|givenName|cn": {"co": "admin"}}

SCIM 2.0 filter syntax (RFC 7644). Basic SCIM filters work through FleX parsing. Complex value filters (emails[type eq "work"]), dotted paths, and URN-qualified attributes are not supported.

cn eq "john"
cn sw "A" and sn pr
not (disabled eq "true")
userName eq "john" or email co "@example.com"
OperatorDescription
eqEquals
neNot equals
coContains
swStarts with
ewEnds with
prPresent (attribute exists)
gtGreater than
geGreater or equal
ltLess than
leLess or equal

Logical operators: and, or, not (...). Group with parentheses.

SCIM operators are valid FleX syntax. FleX adds aliases like = for eq, != for ne, >= for ge, contains for co, and implicit AND via whitespace. See the FleX operators table for the full mapping.


Standard LDAP filter syntax (RFC 4515) for existing LDAP infrastructure.

(cn=john)
(cn=john*)
(&(objectClass=user)(cn=john*))
(|(cn=john)(cn=jane))
(!(disabled=true))
PatternDescription
(attr=value)Equality
(attr=*)Presence (attribute exists)
(attr=prefix*)Starts with
(attr=*suffix)Ends with
(attr=*substring*)Contains
(attr~=value)Approximate match
(attr>=value)Greater or equal
(attr<=value)Less or equal

Composite filters: (&(...)(...)) for AND, (|(...)(...)) for OR, (!(...)) for NOT. Nest freely.

DN-component matching:

(member:dn:=cn=John,ou=users,dc=example,dc=com)
(ou:dn:=Engineering)
LDAPFleX
(cn=John)cn = John
(&(a=1)(b=2))a=1 b=2
(|(a=1)(b=2))a=1 or b=2
(!(a=1))a != 1
(cn=*)cn exists
(cn=John*)cn ^= John
(cn=*John*)cn %= John