diesel_paradedb/lib.rs
1//! Diesel ORM bindings for [ParadeDB](https://www.paradedb.com)'s `pg_search`
2//! extension.
3//!
4//! ParadeDB adds a Postgres type (`pdb.query`), two custom operators (`|||`
5//! and `@@@`), and a family of query-builder functions in the `pdb` schema.
6//! Mainline Diesel does not know about any of these, so queries that use
7//! them must otherwise be written with `sql_query`. This crate bridges that
8//! gap: once imported, BM25 queries, match-all filters, relevance scoring,
9//! and faceting aggregates compose with regular Diesel `select` / `filter`
10//! / `order` calls and are checked at compile time.
11//!
12//! ## What is modelled
13//!
14//! - [`sql_types::ParadeQuery`] — Diesel SQL-type marker that mirrors
15//! ParadeDB's `pdb.query` type. Every `pdb::*` builder function returns
16//! this type, and the `@@@` operator expects it on the right.
17//! - Infix operators [`TermMatch`] (`|||`) and [`ParadeMatch`] (`@@@`),
18//! exposed via the fluent extension traits [`TermMatchDsl`] /
19//! [`ParadeMatchDsl`] (`.term_match(...)` and `.parade_match(...)`).
20//! - Scalar function bindings: [`pdb_all`][fn@pdb_all],
21//! [`pdb_score`][fn@pdb_score].
22//! - Aggregate / window expressions: [`pdb_agg_terms`], [`pdb_agg_avg`],
23//! [`pdb_agg_stats`], [`pdb_agg_value_count`]. Each returns a [`PdbAgg`]
24//! that can be used directly (aggregate form) or via `.over_all()`
25//! (window form, which attaches a facet to every row of a non-grouped
26//! Top-K BM25 query — the shape ParadeDB documents for
27//! search-with-facets).
28//!
29//! ## What is NOT modelled
30//!
31//! - The BM25 index access method itself. Indexes do not live in Diesel's
32//! type system — `CREATE INDEX ... USING bm25 (...)` belongs in your
33//! migrations. This crate type-checks queries that *use* a BM25 index;
34//! existence of the index is a runtime contract.
35//! - The legacy `paradedb.searchqueryinput` type. ParadeDB exposes both
36//! `pdb.query` (newer) and `paradedb.searchqueryinput` (legacy). This
37//! crate models only the newer `pdb.query`.
38//!
39//! ## Quick start
40//!
41//! ```ignore
42//! use diesel::prelude::*;
43//! use diesel_paradedb::{pdb_all, pdb_score, ParadeMatchDsl, TermMatchDsl};
44//!
45//! // Top-5 BM25 hits with score, ordered by relevance.
46//! let rows: Vec<(i32, String, f32)> = my_table::table
47//! .select((my_table::id, my_table::text, pdb_score(my_table::id)))
48//! .filter(my_table::text.term_match("service outage"))
49//! .order(pdb_score(my_table::id).desc())
50//! .limit(5)
51//! .load(conn)?;
52//!
53//! // Match-all + sentiment facet via the window form.
54//! use diesel_paradedb::pdb_agg_terms;
55//! let (id, facet): (i32, serde_json::Value) = my_table::table
56//! .select((my_table::id, pdb_agg_terms("sentiment", 10).over_all()))
57//! .filter(my_table::id.parade_match(pdb_all()))
58//! .order(pdb_score(my_table::id).desc())
59//! .limit(1)
60//! .get_result(conn)?;
61//! ```
62//!
63//! ## Diesel version compatibility
64//!
65//! This crate pins to a single Diesel minor. `diesel-paradedb` `0.1.x`
66//! targets `diesel = "~2.2"`. A Diesel `2.3` release will trigger
67//! `diesel-paradedb` `0.2`; a Diesel `3.0` will trigger
68//! `diesel-paradedb` `3.0` (the crate's major tracks Diesel's).
69//!
70//! ## Async usage
71//!
72//! Works unchanged with [`diesel-async`]: this crate only adds new
73//! expression types and operators, all of which use Diesel's standard
74//! `QueryFragment` / `Expression` traits. No async feature flag is
75//! required.
76//!
77//! [`diesel-async`]: https://crates.io/crates/diesel-async
78
79#![cfg_attr(docsrs, feature(doc_cfg))]
80#![doc(html_root_url = "https://docs.rs/diesel-paradedb/0.1.0")]
81
82mod aggregates;
83mod dsl;
84mod functions;
85mod types;
86
87pub use aggregates::{
88 pdb_agg_avg, pdb_agg_stats, pdb_agg_terms, pdb_agg_value_count, PdbAgg, PdbAggOver,
89};
90pub use dsl::{ParadeMatch, ParadeMatchDsl, TermMatch, TermMatchDsl};
91pub use functions::{pdb_all, pdb_score};
92
93/// SQL-type markers exposed for use in `Queryable` derives and explicit
94/// type annotations on `select(...)` clauses. The convention mirrors
95/// pgvector's `pgvector::sql_types::Vector` re-export.
96pub mod sql_types {
97 pub use crate::types::ParadeQuery;
98}