Expand description
Diesel ORM bindings for ParadeDB’s pg_search
extension.
ParadeDB adds a Postgres type (pdb.query), two custom operators (|||
and @@@), and a family of query-builder functions in the pdb schema.
Mainline Diesel does not know about any of these, so queries that use
them must otherwise be written with sql_query. This crate bridges that
gap: once imported, BM25 queries, match-all filters, relevance scoring,
and faceting aggregates compose with regular Diesel select / filter
/ order calls and are checked at compile time.
§What is modelled
sql_types::ParadeQuery— Diesel SQL-type marker that mirrors ParadeDB’spdb.querytype. Everypdb::*builder function returns this type, and the@@@operator expects it on the right.- Infix operators [
TermMatch] (|||) and [ParadeMatch] (@@@), exposed via the fluent extension traitsTermMatchDsl/ParadeMatchDsl(.term_match(...)and.parade_match(...)). - Scalar function bindings:
pdb_all,pdb_score. - Aggregate / window expressions:
pdb_agg_terms,pdb_agg_avg,pdb_agg_stats,pdb_agg_value_count. Each returns aPdbAggthat can be used directly (aggregate form) or via.over_all()(window form, which attaches a facet to every row of a non-grouped Top-K BM25 query — the shape ParadeDB documents for search-with-facets).
§What is NOT modelled
- The BM25 index access method itself. Indexes do not live in Diesel’s
type system —
CREATE INDEX ... USING bm25 (...)belongs in your migrations. This crate type-checks queries that use a BM25 index; existence of the index is a runtime contract. - The legacy
paradedb.searchqueryinputtype. ParadeDB exposes bothpdb.query(newer) andparadedb.searchqueryinput(legacy). This crate models only the newerpdb.query.
§Quick start
use diesel::prelude::*;
use diesel_paradedb::{pdb_all, pdb_score, ParadeMatchDsl, TermMatchDsl};
// Top-5 BM25 hits with score, ordered by relevance.
let rows: Vec<(i32, String, f32)> = my_table::table
.select((my_table::id, my_table::text, pdb_score(my_table::id)))
.filter(my_table::text.term_match("service outage"))
.order(pdb_score(my_table::id).desc())
.limit(5)
.load(conn)?;
// Match-all + sentiment facet via the window form.
use diesel_paradedb::pdb_agg_terms;
let (id, facet): (i32, serde_json::Value) = my_table::table
.select((my_table::id, pdb_agg_terms("sentiment", 10).over_all()))
.filter(my_table::id.parade_match(pdb_all()))
.order(pdb_score(my_table::id).desc())
.limit(1)
.get_result(conn)?;§Diesel version compatibility
This crate pins to a single Diesel minor. diesel-paradedb 0.1.x
targets diesel = "~2.2". A Diesel 2.3 release will trigger
diesel-paradedb 0.2; a Diesel 3.0 will trigger
diesel-paradedb 3.0 (the crate’s major tracks Diesel’s).
§Async usage
Works unchanged with diesel-async: this crate only adds new
expression types and operators, all of which use Diesel’s standard
QueryFragment / Expression traits. No async feature flag is
required.
Modules§
- sql_
types - SQL-type markers exposed for use in
Queryablederives and explicit type annotations onselect(...)clauses. The convention mirrors pgvector’spgvector::sql_types::Vectorre-export.
Structs§
- PdbAgg
- Aggregate form of
pdb.agg(<json>). Use thepdb_agg_*constructors rather than building this directly — they keep the JSON config private and consistent across call sites. - PdbAgg
Over - Window form of
pdb.agg(<json>) OVER (). Produced byPdbAgg::over_all. Behaves as a non-aggregate expression so it can coexist with normalSELECTcolumns — which is the entire point of usingOVER ()in the search-with-facets pattern.
Traits§
- Parade
Match Dsl - Fluent
.parade_match(...)for structured ParadeDB queries against any column. - Term
Match Dsl - Fluent
.term_match(...)for BM25 term queries against aTextcolumn.
Functions§
- pdb_
agg_ avg pdb.agg('{"avg": {"field": <field>}}')— average of a numeric fast field.- pdb_
agg_ stats pdb.agg('{"stats": {"field": <field>}}')— count / min / max / sum / avg in one pass.- pdb_
agg_ terms pdb.agg('{"terms": {"field": <field>, "size": <size>}}')— bucket-count aggregate over the distinct values of a fast field.- pdb_
agg_ value_ count pdb.agg('{"value_count": {"field": <field>}}')— non-null value count.- pdb_all
pdb.all()— match-all ParadeDB query. Pair with@@@to filter every row through the BM25 index (e.g. so a window-formpdb.agg(...)has a Top-K context to compute over).- pdb_
score pdb.score(key)— BM25 relevance score for the row. Only meaningful inside a query whose@@@/|||filter targets the same BM25 index; outside that context Postgres returns NULL at runtime. Modelled asFloat4(non-nullable in the typical hot path).
Type Aliases§
- pdb_all
- The return type of
pdb_all() - pdb_
score - The return type of
pdb_score()