Instrumentation:
search_engine.compile is emitted by the compiler. See Debugging.Compiled Params boundary
- Public output type:
SearchEngine::CompiledParams— immutable, read-only wrapper around compiled Typesense params. - Determinism:
to_hreturns a symbol-keyed, lexicographically ordered Hash;to_jsonis stable across runs. - Usage: callers may treat it like a Hash for read methods (
[],key?,keys,each) or callto_h. - Construction: internal to the relation/compiler; user code does not instantiate it directly.
SearchEngine::AST into a deterministic Typesense filter_by string. It is pure (no I/O), safe (centralized quoting/escaping), and consistent with the where DSL.
Overview
- Deterministic: same AST → same string; no globals.
- Safe quoting: uses
SearchEngine::Filters::Sanitizerfor all values. - Parentheses & precedence: explicit, predictable rules (
And>Or). - Escape hatch:
AST::Rawis passed through as-is.
Node mapping
| AST node | Syntax | ||
|---|---|---|---|
Eq(field, value) | field:=VALUE | ||
NotEq(field, value) | field:!=VALUE | ||
Gt(field, value) | field:>VALUE | ||
Gte(field, value) | field:>=VALUE | ||
Lt(field, value) | field:<VALUE | ||
Lte(field, value) | field:<=VALUE | ||
In(field, [v1, v2]) | field:=[V1, V2] | ||
NotIn(field, [v1, v2]) | field:!=[V1, V2] | ||
And(n1, n2, ...) | ... && ... | ||
Or(n1, n2, ...) | `… | …` | |
Group(child) | ( ... ) | ||
Raw(fragment) | passthrough |
Matches/Prefix: Typesensefilter_bydoes not support these forms; compilation raisesUnsupportedNode. UseAST::Rawfor adapter-specific fragments if needed.
Quoting & types
Values are rendered viaFilters::Sanitizer.quote:
- String: double-quoted, with minimal escaping for
\and". - Boolean:
true/false. - Nil:
null. - Numeric: as-is (epoch seconds recommended for
:time/:datetime). - Time/Date/DateTime: ISO8601 string (quoted). Upstream parsing coerces Date/DateTime to
Time.utc. When the field type is numeric (:time/:datetime), prefer passing epoch seconds. - Array: one-level flatten; each element quoted; wrapped as
[a, b].
Precedence & parentheses
- Precedence:
And= 20,Or= 10. Leaves bind tighter. Groupalways inserts parentheses.- Parentheses are added when a child has lower precedence than its parent.
- Whitespace: single spaces around
&&and||.
Examples
Integration
Relation#to_typesense_paramsprefers compilingastwhen present, falling back to legacy stringfiltersfor backward compatibility.Rawfragments are preserved through the pipeline.- When joins are applied, joined fields render as
assoc.field:dirinsort_by. Nestedinclude_fieldscompile to$assoc(field1,field2,…)segments emitted before base fields. The finalinclude_fieldsreflects precedence: effective include set = include − exclude (per path); exclude always wins. Empty groups are omitted. - Curation state maps to body params:
pinned_hits,hidden_hits,curation_tags,filter_curated_hits(omitted when empty/nil). See Curation.
Example with joins
The
:_join section is an internal context map for downstream components and may be removed by the HTTP layer before sending the request. See Joins for details.Relation#to_params_json — it uses SearchEngine::CompiledParams to ensure stable ordering.
See also: Relation · Query DSL · Joins
Troubleshooting
- Unsupported node: Use
AST::Rawfor adapter‑specific fragments not supported byfilter_by. - Unexpected quoting: All quoting is centralized in the sanitizer; ensure values are passed as plain Ruby objects.
- Complex precedence: Wrap with
AST.groupto force explicit parentheses.