99
1010## Status
1111
12- Work in progress. See ` design-doc.md ` for the current API proposal and scope.
12+ Work in progress.
1313
1414## Requirements & Compatibility
1515
@@ -58,10 +58,6 @@ Product.search(:description).matching("running", "shoes")
5858 .order(search_score: :desc )
5959```
6060
61- ## Arel Layer
62-
63- The user API is built on top of a dedicated Arel layer. See ` AREL_README.md ` for Arel node usage and SQL rendering.
64-
6561## Query Types (Summary)
6662
6763- ` matching ` / ` matching(any: [...]) `
@@ -73,7 +69,62 @@ The user API is built on top of a dedicated Arel layer. See `AREL_README.md` for
7369- ` with_score ` , ` with_snippet `
7470- ` facets ` , ` with_facets `
7571
76- For the full user-facing API, see ` design-doc.md ` .
72+ ## Arel Layer
73+
74+ The user API is built on top of a dedicated Arel layer that provides an AST and SQL renderer for ParadeDB operators.
75+
76+ ### Quickstart
77+
78+ ``` ruby
79+ require " parade_db/arel"
80+
81+ arel = ParadeDB ::Arel ::Builder .new (:products )
82+
83+ predicate = arel.match(:description , " running" , " shoes" )
84+ .and(arel.regex(:description , " run.*" ))
85+ .and(arel.match(:in_stock , true ))
86+
87+ sql = ParadeDB ::Arel .to_sql(predicate)
88+ # => ("products"."description" &&& 'running shoes' AND "products"."description" @@@ pdb.regex('run.*') AND "products"."in_stock" === true)
89+ ```
90+
91+ Render any node with ` ParadeDB::Arel.to_sql(node) ` . All nodes respond to ` .and ` , ` .or ` , and ` .not ` .
92+
93+ ### Builder Methods
94+
95+ | Method | ParadeDB SQL |
96+ | --------| --------------|
97+ | ` match(column, *terms, boost: nil) ` | ` column &&& 'a b'::pdb.boost(N) ` |
98+ | ` match_any(column, *terms) ` | ` column \|\|\| 'a b' ` |
99+ | ` phrase(column, text, slop: n) ` | ` column ### 'text'::pdb.slop(n) ` |
100+ | ` term(column, term, boost: nil) ` | ` column === 'term'::pdb.boost(N) ` |
101+ | ` fuzzy(column, term, distance:, prefix:, boost:) ` | ` column === 'term'::pdb.fuzzy(d[, "true"])::pdb.boost(N) ` |
102+ | ` regex(column, pattern) ` | ` column @@@ pdb.regex('pattern') ` |
103+ | ` near(column, a, b, distance:) ` | ` column @@@ ('a' ## d ## 'b') ` |
104+ | ` phrase_prefix(column, *terms) ` | ` column @@@ pdb.phrase_prefix(ARRAY['a','b']) ` |
105+ | ` full_text(column, expr) ` | ` column @@@ expr ` (raw right-hand value) |
106+ | ` more_like_this(column, key, fields: [:f1, :f2]) ` | ` column @@@ pdb.more_like_this(key, ARRAY['f1','f2']) ` |
107+ | ` score(key_field) ` | ` pdb.score(key_field) ` |
108+ | ` snippet(column, start, finish, max) ` | ` pdb.snippet(column, start, finish, max) ` |
109+ | ` agg(json) ` | ` pdb.agg(json) ` |
110+
111+ ` Builder#[] ` returns a column node for manual composition: ` arel[:description] ` .
112+
113+ ### Composition
114+
115+ Boolean composition uses the standard helpers:
116+
117+ ``` ruby
118+ fast = arel.match(:description , " running" ).and(arel.term(:rating , 4 ))
119+ cheap = arel.match(:description , " budget" )
120+ predicate = fast.or(cheap.not)
121+ ```
122+
123+ ` predicate ` renders to:
124+
125+ ``` sql
126+ ((" products" ." description" &&& ' running' AND " products" ." rating" === 4 ) OR NOT (" products" ." description" &&& ' budget' ))
127+ ```
77128
78129## License
79130
0 commit comments