1use std::marker::PhantomData;
11
12use serde_json::{Map, Value};
13
14use super::{
15 Common, FlussoValue, RangeRelation, Sort, SortOrder, Sortable, common_opts, exists_q, kind,
16 single, wrap,
17};
18use crate::FlussoDocument;
19use crate::query::{AsQuery, Query, Root};
20
21fn date_value(value: &impl FlussoValue<kind::Date>) -> Value {
26 match serde_json::to_value(value) {
27 Ok(Value::String(string)) => Value::String(string),
28 Ok(other) => Value::String(other.to_string()),
29 Err(_) => Value::String(String::new()),
30 }
31}
32
33fn number_value<K>(value: &impl FlussoValue<K>) -> Value {
39 match serde_json::to_value(value) {
40 Ok(Value::String(string)) => string
41 .parse::<serde_json::Number>()
42 .map_or(Value::String(string), Value::Number),
43 Ok(other) => other,
44 Err(_) => Value::Null,
45 }
46}
47
48fn bool_value(value: &impl FlussoValue<kind::Bool>) -> Value {
51 serde_json::to_value(value).unwrap_or(Value::Null)
52}
53
54#[derive(Debug, Clone)]
57pub struct EqQuery<S = Root> {
58 path: String,
59 value: Value,
60 common: Common,
61 _scope: PhantomData<fn() -> S>,
62}
63
64impl<S> EqQuery<S> {
65 fn new(path: &str, value: Value) -> Self {
66 Self {
67 path: path.to_string(),
68 value,
69 common: Common::default(),
70 _scope: PhantomData,
71 }
72 }
73
74 common_opts!(common);
75}
76
77impl<S> AsQuery<S> for EqQuery<S> {
78 fn into_query(self) -> Option<Query<S>> {
79 if self.common.is_empty() {
80 Some(single("term", &self.path, self.value))
81 } else {
82 let mut body = Map::new();
83 body.insert("value".to_string(), self.value);
84 self.common.write(&mut body);
85 Some(single("term", &self.path, Value::Object(body)))
86 }
87 }
88}
89
90#[derive(Debug, Clone)]
93pub struct TermsQuery<S = Root> {
94 path: String,
95 values: Vec<Value>,
96 common: Common,
97 _scope: PhantomData<fn() -> S>,
98}
99
100impl<S> TermsQuery<S> {
101 pub(crate) fn new(path: &str, values: Vec<Value>) -> Self {
102 Self {
103 path: path.to_string(),
104 values,
105 common: Common::default(),
106 _scope: PhantomData,
107 }
108 }
109
110 common_opts!(common);
111}
112
113impl<S> AsQuery<S> for TermsQuery<S> {
114 fn into_query(self) -> Option<Query<S>> {
115 let mut body = Map::new();
117 body.insert(self.path, Value::Array(self.values));
118 self.common.write(&mut body);
119 Some(wrap("terms", body))
120 }
121}
122
123#[derive(Debug, Clone)]
126pub struct RangeQuery<S = Root> {
127 path: String,
128 bounds: Vec<(&'static str, Value)>,
129 extra: Map<String, Value>,
130 common: Common,
131 _scope: PhantomData<fn() -> S>,
132}
133
134impl<S> RangeQuery<S> {
135 pub(crate) fn new(path: &str, bounds: Vec<(&'static str, Value)>) -> Self {
136 Self {
137 path: path.to_string(),
138 bounds,
139 extra: Map::new(),
140 common: Common::default(),
141 _scope: PhantomData,
142 }
143 }
144
145 #[must_use]
147 pub fn format(mut self, format: impl Into<String>) -> Self {
148 self.extra
149 .insert("format".to_string(), Value::String(format.into()));
150 self
151 }
152
153 #[must_use]
155 pub fn time_zone(mut self, time_zone: impl Into<String>) -> Self {
156 self.extra
157 .insert("time_zone".to_string(), Value::String(time_zone.into()));
158 self
159 }
160
161 #[must_use]
164 pub fn relation(mut self, relation: RangeRelation) -> Self {
165 self.extra.insert(
166 "relation".to_string(),
167 Value::String(relation.as_str().to_string()),
168 );
169 self
170 }
171
172 common_opts!(common);
173}
174
175impl<S> AsQuery<S> for RangeQuery<S> {
176 fn into_query(self) -> Option<Query<S>> {
177 let mut body = self.extra;
178 for (key, value) in self.bounds {
179 body.insert(key.to_string(), value);
180 }
181 self.common.write(&mut body);
182 Some(single("range", &self.path, Value::Object(body)))
183 }
184}
185
186#[derive(Debug, Clone)]
188pub struct Bool<S = Root> {
189 path: String,
190 _scope: PhantomData<fn() -> S>,
191}
192
193impl<S> Bool<S> {
194 pub fn at(path: impl Into<String>) -> Self {
195 Self {
196 path: path.into(),
197 _scope: PhantomData,
198 }
199 }
200
201 pub fn eq(&self, value: impl FlussoValue<kind::Bool>) -> EqQuery<S> {
203 EqQuery::new(&self.path, bool_value(&value))
204 }
205
206 pub fn exists(&self) -> Query<S> {
208 exists_q(&self.path)
209 }
210}
211
212impl<S: FlussoDocument> Sortable for Bool<S> {
213 fn asc(&self) -> Sort {
214 Sort::field::<S>(&self.path, SortOrder::Asc)
215 }
216 fn desc(&self) -> Sort {
217 Sort::field::<S>(&self.path, SortOrder::Desc)
218 }
219}
220
221#[derive(Debug, Clone)]
229pub struct Number<K, S = Root> {
230 path: String,
231 _marker: PhantomData<fn() -> (K, S)>,
232}
233
234impl<K, S> Number<K, S> {
235 pub fn at(path: impl Into<String>) -> Self {
236 Self {
237 path: path.into(),
238 _marker: PhantomData,
239 }
240 }
241
242 pub fn eq(&self, value: impl FlussoValue<K>) -> EqQuery<S> {
244 EqQuery::new(&self.path, number_value(&value))
245 }
246
247 pub fn any_of(&self, values: impl IntoIterator<Item = impl FlussoValue<K>>) -> TermsQuery<S> {
249 let array = values.into_iter().map(|v| number_value(&v)).collect();
250 TermsQuery::new(&self.path, array)
251 }
252
253 pub fn lt(&self, value: impl FlussoValue<K>) -> RangeQuery<S> {
255 RangeQuery::new(&self.path, vec![("lt", number_value(&value))])
256 }
257
258 pub fn lte(&self, value: impl FlussoValue<K>) -> RangeQuery<S> {
260 RangeQuery::new(&self.path, vec![("lte", number_value(&value))])
261 }
262
263 pub fn gt(&self, value: impl FlussoValue<K>) -> RangeQuery<S> {
265 RangeQuery::new(&self.path, vec![("gt", number_value(&value))])
266 }
267
268 pub fn gte(&self, value: impl FlussoValue<K>) -> RangeQuery<S> {
270 RangeQuery::new(&self.path, vec![("gte", number_value(&value))])
271 }
272
273 pub fn between(&self, low: impl FlussoValue<K>, high: impl FlussoValue<K>) -> RangeQuery<S> {
275 RangeQuery::new(
276 &self.path,
277 vec![("gte", number_value(&low)), ("lte", number_value(&high))],
278 )
279 }
280
281 pub fn exists(&self) -> Query<S> {
283 exists_q(&self.path)
284 }
285}
286
287impl<K, S: FlussoDocument> Sortable for Number<K, S> {
288 fn asc(&self) -> Sort {
289 Sort::field::<S>(&self.path, SortOrder::Asc)
290 }
291 fn desc(&self) -> Sort {
292 Sort::field::<S>(&self.path, SortOrder::Desc)
293 }
294}
295
296#[derive(Debug, Clone)]
298pub struct Date<S = Root> {
299 path: String,
300 _scope: PhantomData<fn() -> S>,
301}
302
303impl<S> Date<S> {
304 pub fn at(path: impl Into<String>) -> Self {
305 Self {
306 path: path.into(),
307 _scope: PhantomData,
308 }
309 }
310
311 pub fn eq(&self, value: impl FlussoValue<kind::Date>) -> EqQuery<S> {
314 EqQuery::new(&self.path, date_value(&value))
315 }
316
317 pub fn any_of(
319 &self,
320 values: impl IntoIterator<Item = impl FlussoValue<kind::Date>>,
321 ) -> TermsQuery<S> {
322 let array = values.into_iter().map(|v| date_value(&v)).collect();
323 TermsQuery::new(&self.path, array)
324 }
325
326 pub fn lt(&self, value: impl FlussoValue<kind::Date>) -> RangeQuery<S> {
328 RangeQuery::new(&self.path, vec![("lt", date_value(&value))])
329 }
330
331 pub fn lte(&self, value: impl FlussoValue<kind::Date>) -> RangeQuery<S> {
333 RangeQuery::new(&self.path, vec![("lte", date_value(&value))])
334 }
335
336 pub fn gt(&self, value: impl FlussoValue<kind::Date>) -> RangeQuery<S> {
338 RangeQuery::new(&self.path, vec![("gt", date_value(&value))])
339 }
340
341 pub fn gte(&self, value: impl FlussoValue<kind::Date>) -> RangeQuery<S> {
343 RangeQuery::new(&self.path, vec![("gte", date_value(&value))])
344 }
345
346 pub fn between(
348 &self,
349 low: impl FlussoValue<kind::Date>,
350 high: impl FlussoValue<kind::Date>,
351 ) -> RangeQuery<S> {
352 RangeQuery::new(
353 &self.path,
354 vec![("gte", date_value(&low)), ("lte", date_value(&high))],
355 )
356 }
357
358 pub fn exists(&self) -> Query<S> {
360 exists_q(&self.path)
361 }
362}
363
364impl<S: FlussoDocument> Sortable for Date<S> {
365 fn asc(&self) -> Sort {
366 Sort::field::<S>(&self.path, SortOrder::Asc)
367 }
368 fn desc(&self) -> Sort {
369 Sort::field::<S>(&self.path, SortOrder::Desc)
370 }
371}