Skip to main content

couchbase_core/searchx/
query_options.rs

1/*
2 *
3 *  * Copyright (c) 2025 Couchbase, Inc.
4 *  *
5 *  * Licensed under the Apache License, Version 2.0 (the "License");
6 *  * you may not use this file except in compliance with the License.
7 *  * You may obtain a copy of the License at
8 *  *
9 *  *    http://www.apache.org/licenses/LICENSE-2.0
10 *  *
11 *  * Unless required by applicable law or agreed to in writing, software
12 *  * distributed under the License is distributed on an "AS IS" BASIS,
13 *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  * See the License for the specific language governing permissions and
15 *  * limitations under the License.
16 *
17 */
18
19use crate::httpx::request::OnBehalfOfInfo;
20use crate::searchx::facets::Facet;
21use crate::searchx::queries::Query;
22use crate::searchx::sort::Sort;
23use serde::ser::{SerializeMap, SerializeSeq};
24use serde::{Serialize, Serializer};
25use std::collections::HashMap;
26
27#[derive(Debug, Clone, PartialEq)]
28#[non_exhaustive]
29pub struct Location {
30    pub lat: f64,
31    pub lon: f64,
32}
33
34impl Location {
35    pub fn new(lat: f64, lon: f64) -> Self {
36        Self { lat, lon }
37    }
38}
39
40impl Serialize for Location {
41    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
42    where
43        S: Serializer,
44    {
45        let mut seq = serializer.serialize_seq(Some(2))?;
46        seq.serialize_element(&self.lon)?;
47        seq.serialize_element(&self.lat)?;
48
49        seq.end()
50    }
51}
52
53#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
54#[serde(rename_all = "lowercase")]
55#[non_exhaustive]
56pub enum HighlightStyle {
57    Html,
58    Ansi,
59}
60
61#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
62#[non_exhaustive]
63pub enum ConsistencyLevel {
64    #[serde(rename = "")]
65    NotBounded,
66    #[serde(rename = "at_plus")]
67    AtPlus,
68}
69
70#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
71#[serde(rename_all = "lowercase")]
72#[non_exhaustive]
73pub enum ConsistencyResults {
74    Complete,
75}
76
77#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize)]
78#[non_exhaustive]
79pub struct Highlight {
80    #[serde(skip_serializing_if = "Option::is_none")]
81    pub style: Option<HighlightStyle>,
82    #[serde(skip_serializing_if = "Option::is_none")]
83    pub fields: Option<Vec<String>>,
84}
85
86impl Highlight {
87    pub fn new() -> Self {
88        Default::default()
89    }
90
91    pub fn style(mut self, style: impl Into<Option<HighlightStyle>>) -> Self {
92        self.style = style.into();
93        self
94    }
95
96    pub fn fields(mut self, fields: impl Into<Option<Vec<String>>>) -> Self {
97        self.fields = fields.into();
98        self
99    }
100}
101
102pub type ConsistencyVectors = HashMap<String, HashMap<String, u64>>;
103
104#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize)]
105#[non_exhaustive]
106pub struct Consistency {
107    #[serde(skip_serializing_if = "Option::is_none")]
108    pub level: Option<ConsistencyLevel>,
109    #[serde(skip_serializing_if = "Option::is_none")]
110    pub results: Option<ConsistencyResults>,
111    #[serde(skip_serializing_if = "Option::is_none")]
112    pub vectors: Option<ConsistencyVectors>,
113}
114
115impl Consistency {
116    pub fn new() -> Self {
117        Default::default()
118    }
119
120    pub fn level(mut self, level: impl Into<Option<ConsistencyLevel>>) -> Self {
121        self.level = level.into();
122        self
123    }
124
125    pub fn results(mut self, results: impl Into<Option<ConsistencyResults>>) -> Self {
126        self.results = results.into();
127        self
128    }
129
130    pub fn vectors(mut self, vectors: impl Into<Option<ConsistencyVectors>>) -> Self {
131        self.vectors = vectors.into();
132        self
133    }
134}
135
136#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize)]
137#[non_exhaustive]
138pub struct Control {
139    #[serde(skip_serializing_if = "Option::is_none")]
140    pub consistency: Option<Consistency>,
141    #[serde(skip_serializing_if = "Option::is_none")]
142    pub timeout: Option<u64>,
143}
144
145impl Control {
146    pub fn new() -> Self {
147        Default::default()
148    }
149
150    pub fn consistency(mut self, consistency: impl Into<Option<Consistency>>) -> Self {
151        self.consistency = consistency.into();
152        self
153    }
154
155    pub fn timeout(mut self, timeout: impl Into<Option<u64>>) -> Self {
156        self.timeout = timeout.into();
157        self
158    }
159}
160
161#[derive(Debug, Clone, PartialEq, Serialize)]
162#[non_exhaustive]
163pub struct KnnQuery {
164    #[serde(skip_serializing_if = "Option::is_none")]
165    pub boost: Option<f32>,
166    pub field: String,
167    pub k: i64,
168    #[serde(skip_serializing_if = "Option::is_none")]
169    pub vector: Option<Vec<f32>>,
170    #[serde(skip_serializing_if = "Option::is_none")]
171    pub vector_base64: Option<String>,
172    #[serde(skip_serializing_if = "Option::is_none")]
173    pub filter: Option<Query>,
174}
175
176impl KnnQuery {
177    pub fn new(field: impl Into<String>, k: impl Into<i64>) -> Self {
178        Self {
179            boost: None,
180            field: field.into(),
181            k: k.into(),
182            vector: None,
183            vector_base64: None,
184            filter: None,
185        }
186    }
187
188    pub fn boost(mut self, boost: impl Into<Option<f32>>) -> Self {
189        self.boost = boost.into();
190        self
191    }
192
193    pub fn k(mut self, k: impl Into<i64>) -> Self {
194        self.k = k.into();
195        self
196    }
197
198    pub fn vector(mut self, vector: impl Into<Option<Vec<f32>>>) -> Self {
199        self.vector = vector.into();
200        self
201    }
202
203    pub fn vector_base64(mut self, vector_base64: impl Into<Option<String>>) -> Self {
204        self.vector_base64 = vector_base64.into();
205        self
206    }
207
208    pub fn filter(mut self, filter: impl Into<Option<Query>>) -> Self {
209        self.filter = filter.into();
210        self
211    }
212}
213
214#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
215#[serde(rename_all = "lowercase")]
216#[non_exhaustive]
217pub enum KnnOperator {
218    Or,
219    And,
220}
221
222#[derive(Debug, Default, Clone, PartialEq, Serialize)]
223#[non_exhaustive]
224pub struct QueryOptions {
225    #[serde(skip_serializing_if = "Option::is_none")]
226    pub(crate) collections: Option<Vec<String>>,
227    #[serde(skip_serializing_if = "Option::is_none", rename = "ctl")]
228    pub(crate) control: Option<Control>,
229    #[serde(skip_serializing_if = "Option::is_none")]
230    pub(crate) explain: Option<bool>,
231    #[serde(skip_serializing_if = "Option::is_none")]
232    pub(crate) facets: Option<HashMap<String, Facet>>,
233    #[serde(skip_serializing_if = "Option::is_none")]
234    pub(crate) fields: Option<Vec<String>>,
235    #[serde(skip_serializing_if = "Option::is_none")]
236    pub(crate) from: Option<u32>,
237    #[serde(skip_serializing_if = "Option::is_none")]
238    pub(crate) highlight: Option<Highlight>,
239    #[serde(skip_serializing_if = "Option::is_none", rename = "includeLocations")]
240    pub(crate) include_locations: Option<bool>,
241    #[serde(skip_serializing_if = "Option::is_none")]
242    pub(crate) query: Option<Query>,
243    #[serde(skip_serializing_if = "Option::is_none")]
244    pub(crate) score: Option<String>,
245    #[serde(skip_serializing_if = "Option::is_none")]
246    pub(crate) search_after: Option<Vec<String>>,
247    #[serde(skip_serializing_if = "Option::is_none")]
248    pub(crate) search_before: Option<Vec<String>>,
249    #[serde(skip_serializing_if = "Option::is_none", rename = "showrequest")]
250    pub(crate) show_request: Option<bool>,
251    #[serde(skip_serializing_if = "Option::is_none")]
252    pub(crate) size: Option<u32>,
253    #[serde(skip_serializing_if = "Option::is_none")]
254    pub(crate) sort: Option<Vec<Sort>>,
255    #[serde(skip_serializing_if = "Option::is_none")]
256    pub(crate) knn: Option<Vec<KnnQuery>>,
257    #[serde(skip_serializing_if = "Option::is_none")]
258    pub(crate) knn_operator: Option<KnnOperator>,
259
260    #[serde(skip_serializing_if = "Option::is_none", flatten)]
261    pub(crate) raw: Option<HashMap<String, serde_json::Value>>,
262
263    #[serde(skip_serializing)]
264    pub(crate) index_name: String,
265    #[serde(skip_serializing)]
266    pub(crate) scope_name: Option<String>,
267    #[serde(skip_serializing)]
268    pub(crate) bucket_name: Option<String>,
269
270    #[serde(skip_serializing)]
271    pub(crate) on_behalf_of: Option<OnBehalfOfInfo>,
272}
273
274impl QueryOptions {
275    pub fn new(index_name: impl Into<String>) -> Self {
276        Self {
277            collections: None,
278            control: None,
279            explain: None,
280            facets: None,
281            fields: None,
282            from: None,
283            highlight: None,
284            include_locations: None,
285            query: None,
286            score: None,
287            search_after: None,
288            search_before: None,
289            show_request: None,
290            size: None,
291            sort: None,
292            knn: None,
293            knn_operator: None,
294            raw: None,
295            index_name: index_name.into(),
296            scope_name: None,
297            bucket_name: None,
298            on_behalf_of: None,
299        }
300    }
301
302    pub fn collections(mut self, collections: impl Into<Option<Vec<String>>>) -> Self {
303        self.collections = collections.into();
304        self
305    }
306
307    pub fn control(mut self, control: impl Into<Option<Control>>) -> Self {
308        self.control = control.into();
309        self
310    }
311
312    pub fn explain(mut self, explain: impl Into<Option<bool>>) -> Self {
313        self.explain = explain.into();
314        self
315    }
316
317    pub fn facets(mut self, facets: impl Into<Option<HashMap<String, Facet>>>) -> Self {
318        self.facets = facets.into();
319        self
320    }
321
322    pub fn fields(mut self, fields: impl Into<Option<Vec<String>>>) -> Self {
323        self.fields = fields.into();
324        self
325    }
326
327    pub fn from(mut self, from: impl Into<Option<u32>>) -> Self {
328        self.from = from.into();
329        self
330    }
331
332    pub fn highlight(mut self, highlight: impl Into<Option<Highlight>>) -> Self {
333        self.highlight = highlight.into();
334        self
335    }
336
337    pub fn include_locations(mut self, include_locations: impl Into<Option<bool>>) -> Self {
338        self.include_locations = include_locations.into();
339        self
340    }
341
342    pub fn query(mut self, query: impl Into<Option<Query>>) -> Self {
343        self.query = query.into();
344        self
345    }
346
347    pub fn score(mut self, score: impl Into<Option<String>>) -> Self {
348        self.score = score.into();
349        self
350    }
351
352    pub fn search_after(mut self, search_after: impl Into<Option<Vec<String>>>) -> Self {
353        self.search_after = search_after.into();
354        self
355    }
356
357    pub fn search_before(mut self, search_before: impl Into<Option<Vec<String>>>) -> Self {
358        self.search_before = search_before.into();
359        self
360    }
361
362    pub fn show_request(mut self, show_request: impl Into<Option<bool>>) -> Self {
363        self.show_request = show_request.into();
364        self
365    }
366
367    pub fn size(mut self, size: impl Into<Option<u32>>) -> Self {
368        self.size = size.into();
369        self
370    }
371
372    pub fn sort(mut self, sort: impl Into<Option<Vec<Sort>>>) -> Self {
373        self.sort = sort.into();
374        self
375    }
376
377    pub fn knn(mut self, knn: impl Into<Option<Vec<KnnQuery>>>) -> Self {
378        self.knn = knn.into();
379        self
380    }
381
382    pub fn knn_operator(mut self, knn_operator: impl Into<Option<KnnOperator>>) -> Self {
383        self.knn_operator = knn_operator.into();
384        self
385    }
386
387    pub fn raw(mut self, raw: impl Into<Option<HashMap<String, serde_json::Value>>>) -> Self {
388        self.raw = raw.into();
389        self
390    }
391
392    pub fn scope_name(mut self, scope_name: impl Into<Option<String>>) -> Self {
393        self.scope_name = scope_name.into();
394        self
395    }
396
397    pub fn bucket_name(mut self, bucket_name: impl Into<Option<String>>) -> Self {
398        self.bucket_name = bucket_name.into();
399        self
400    }
401
402    pub fn on_behalf_of(mut self, on_behalf_of: impl Into<Option<OnBehalfOfInfo>>) -> Self {
403        self.on_behalf_of = on_behalf_of.into();
404        self
405    }
406}