1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
//! `flusso-query` — a typed query client for a flusso-maintained search index.
//!
//! Targets OpenSearch and Elasticsearch 7.x, which share the `_search` query DSL
//! this crate emits; any future backend divergence is handled on the [`Client`],
//! not by separate crates.
//!
//! This is the **runtime** layer described in [`CLIENT.md`](../../../CLIENT.md):
//! the transport, the field-handle / [`Query`] / [`Search`] builder, and the
//! typed [`SearchResponse`]. It is generic over the caller's document type `T`.
//!
//! # What this first cut covers
//!
//! - [`Client`] transport over OpenSearch (`connect`, `basic_auth`, search,
//! msearch, get).
//! - Field handles ([`Keyword`], [`Text`], [`Bool`], [`Number`], [`Date`],
//! [`Nested`], [`Binary`], [`Json`]) with operators that build a [`Query`].
//! - [`Query`] composition (`and` / `or` / `not`) and the [`Search`] bool-clause
//! builder (`query` / `filter` / `must_not` / `should`, plus `sort` / `from` /
//! `size` / `raw`). A [`Search`] is a plain client-free value — build it
//! anywhere, store and reuse it; a [`Client`] appears only at the terminals:
//! [`Search::send`] (a typed page), [`Search::ids`] (a page of bare document
//! ids, `_source: false`), or [`Search::count`] (just the number of matches,
//! via `_count`).
//! - Several searches in one round-trip: [`Client::msearch`] (a tuple of
//! `&Search<T>`, mixed document types, one typed response per slot) and
//! [`Client::msearch_all`] (a slice of one type).
//! - Combined (blended) search: [`FlussoMultiDocument`] — a caller-owned enum
//! with one variant per document type — and its [`MultiSearch`] builder. One
//! query across all the union's indexes, one relevance-ranked result list,
//! each hit decoded into the variant matching its physical `_index`.
//! - Typed [`SearchResponse`] / [`Hit`].
//!
//! Also covered: optional filters (`Option<Q>` is a [`Query`]); object/to-one-join
//! handles ([`Object`]); shaping returned nested arrays ([`Search::filter_nested`]
//! with [`Nested::matching`], via `inner_hits`); and scope-tagged queries —
//! [`Query`]`<S>` carries the scope `S` it was built in ([`Root`] for the document
//! root and flattened objects, the element type for a `nested` array), so a nested
//! query must be lifted through [`Nested::any`]/[`Nested::all`] before it can join a
//! root query; the compiler enforces it.
//!
//! # Not yet built (see CLIENT.md for the endgame)
//!
//! - The `#[derive(FlussoDocument)]` and `#[derive(FlussoMultiDocument)]`
//! proc-macros live in `flusso-query-derive` (the `derive` feature). Without
//! them, document structs + handles and union impls are written by hand —
//! exactly the calls this crate exposes (see the integration tests).
//! - `filter_nested`'s `keep_source()` opt-out (it always replaces the array in
//! `source` today) and a typed `hit.nested(handle)` accessor.
//!
//! # Example (hand-written until the derive lands)
//!
//! ```no_run
//! use flusso_query::{Client, Keyword, Number, Nested, kind};
//!
//! #[derive(serde::Deserialize)]
//! struct User {
//! email: String,
//! #[serde(rename = "orderCount")]
//! order_count: i64,
//! }
//!
//! impl User {
//! fn email() -> Keyword { Keyword::at("email") }
//! fn order_count() -> Number<kind::Long> { Number::at("orderCount") }
//! fn query() -> flusso_query::Search<User> {
//! flusso_query::Search::new("users", "xxxxxx")
//! }
//! }
//!
//! # async fn run() -> flusso_query::Result<()> {
//! // A query is a plain value — no client involved while building it.
//! let busy = User::query()
//! .filter(User::email().eq("ada@example.com"))
//! .filter(User::order_count().gte(5))
//! .size(20);
//!
//! // The client appears once, when it's time to run.
//! let client = Client::connect("https://localhost:9200")?;
//! let page = busy.send(&client).await?;
//! println!("{} matches", page.total);
//! # Ok(())
//! # }
//! ```
pub use Client;
pub use ;
pub use ;
pub use MsearchBundle;
pub use ;
pub use ;
pub use ;
/// `#[derive(FlussoDocument)]` — generates the typed query surface for a
/// hand-written document struct (its field handles) and implements the
/// [`FlussoDocument`](trait@FlussoDocument) trait (`INDEX`/`SCHEMA_HASH` +
/// `search`/`get`). See [`CLIENT.md`](../../../CLIENT.md). Enabled by the
/// `derive` feature.
pub use FlussoDocument;
/// `#[derive(FlussoValue)]` — implements [`trait@FlussoValue`] for an enum or newtype
/// wrapper, so it may stand in for a field of the chosen kind (`#[flusso(keyword)]`
/// — the default — `#[flusso(text)]`, `#[flusso(number)]`, or `#[flusso(date)]`)
/// in a [`FlussoDocument`] struct. Enabled by the `derive` feature.
pub use FlussoValue;
/// `#[derive(FlussoMap)]` — implements [`trait@FlussoMap`] for a newtype wrapper
/// over a `map` field, so it may stand in for a `map` of the chosen value kind
/// (`#[flusso(keyword)]` — the default — `#[flusso(text)]`, `#[flusso(number)]`,
/// or `#[flusso(date)]`) in a [`FlussoDocument`] struct. A bare
/// `HashMap<String, V>` needs no derive. Enabled by the `derive` feature.
pub use FlussoMap;
/// `#[derive(FlussoMultiDocument)]` — implements [`trait@FlussoMultiDocument`]
/// for an enum with one single-field variant per document type (the
/// combined-search union): the generated impl lists every variant's index and
/// decodes each hit into the variant matching its physical `_index`. Enabled
/// by the `derive` feature.
pub use FlussoMultiDocument;
// The multi-document derive's generated code deserializes variant payloads;
// routing it through this re-export keeps it on this crate's `serde_json`.
// Hidden: not API.
pub use serde_json as __serde_json;
/// `rust_decimal::Decimal`, re-exported for `decimal` fields. Enabled by the
/// `decimal` feature.
pub use Decimal;
/// `chrono`, re-exported for `date`/`timestamp` fields. Enabled by the `chrono`
/// feature.
pub use chrono;
/// `uuid`, re-exported for `keyword` id / foreign-key fields. With this feature
/// a `uuid::Uuid` field needs no `#[flusso(skip)]` and `id().eq(some_uuid)`
/// works without `.to_string()`. Enabled by the `uuid` feature.
pub use uuid;