Skip to main content

sift_query_core/query/builder/
operators.rs

1use crate::{CustomOperator, FieldRef, IntoScalarValue, Operator, ScalarValue, SearchEntity};
2
3use super::QueryBuilder;
4
5impl<E: SearchEntity> QueryBuilder<'_, E> {
6    #[must_use]
7    pub fn eq<T: IntoScalarValue, K>(self, field: FieldRef<E, T, K>, value: T) -> Self {
8        self.push_condition(
9            field.id(),
10            Operator::Eq,
11            vec![value.into_scalar_value()],
12            false,
13        )
14    }
15
16    #[must_use]
17    pub fn ne<T: IntoScalarValue, K>(self, field: FieldRef<E, T, K>, value: T) -> Self {
18        self.push_condition(
19            field.id(),
20            Operator::Ne,
21            vec![value.into_scalar_value()],
22            false,
23        )
24    }
25
26    #[must_use]
27    pub fn gt<T: IntoScalarValue, K>(self, field: FieldRef<E, T, K>, value: T) -> Self {
28        self.push_condition(
29            field.id(),
30            Operator::Gt,
31            vec![value.into_scalar_value()],
32            false,
33        )
34    }
35
36    #[must_use]
37    pub fn ge<T: IntoScalarValue, K>(self, field: FieldRef<E, T, K>, value: T) -> Self {
38        self.push_condition(
39            field.id(),
40            Operator::Ge,
41            vec![value.into_scalar_value()],
42            false,
43        )
44    }
45
46    #[must_use]
47    pub fn lt<T: IntoScalarValue, K>(self, field: FieldRef<E, T, K>, value: T) -> Self {
48        self.push_condition(
49            field.id(),
50            Operator::Lt,
51            vec![value.into_scalar_value()],
52            false,
53        )
54    }
55
56    #[must_use]
57    pub fn le<T: IntoScalarValue, K>(self, field: FieldRef<E, T, K>, value: T) -> Self {
58        self.push_condition(
59            field.id(),
60            Operator::Le,
61            vec![value.into_scalar_value()],
62            false,
63        )
64    }
65
66    #[must_use]
67    pub fn between<T: IntoScalarValue, K>(
68        self,
69        field: FieldRef<E, T, K>,
70        lower: T,
71        upper: T,
72    ) -> Self {
73        self.push_condition(
74            field.id(),
75            Operator::Between,
76            vec![lower.into_scalar_value(), upper.into_scalar_value()],
77            false,
78        )
79    }
80
81    #[must_use]
82    pub fn not_between<T: IntoScalarValue, K>(
83        self,
84        field: FieldRef<E, T, K>,
85        lower: T,
86        upper: T,
87    ) -> Self {
88        self.push_condition(
89            field.id(),
90            Operator::NotBetween,
91            vec![lower.into_scalar_value(), upper.into_scalar_value()],
92            false,
93        )
94    }
95
96    #[must_use]
97    pub fn in_list<T, K, I>(self, field: FieldRef<E, T, K>, values: I) -> Self
98    where
99        T: IntoScalarValue,
100        I: IntoIterator<Item = T>,
101    {
102        self.list(field, Operator::InList, values)
103    }
104
105    #[must_use]
106    pub fn not_in<T, K, I>(self, field: FieldRef<E, T, K>, values: I) -> Self
107    where
108        T: IntoScalarValue,
109        I: IntoIterator<Item = T>,
110    {
111        self.list(field, Operator::NotIn, values)
112    }
113
114    #[must_use]
115    pub fn is_null<T, K>(self, field: FieldRef<E, T, K>) -> Self {
116        self.push_condition(field.id(), Operator::IsNull, Vec::new(), false)
117    }
118
119    #[must_use]
120    pub fn is_not_null<T, K>(self, field: FieldRef<E, T, K>) -> Self {
121        self.push_condition(field.id(), Operator::NotNull, Vec::new(), false)
122    }
123
124    #[must_use]
125    pub fn empty<K>(self, field: FieldRef<E, String, K>) -> Self {
126        self.push_condition(field.id(), Operator::Empty, Vec::new(), false)
127    }
128
129    #[must_use]
130    pub fn not_empty<K>(self, field: FieldRef<E, String, K>) -> Self {
131        self.push_condition(field.id(), Operator::NotEmpty, Vec::new(), false)
132    }
133
134    #[must_use]
135    pub fn always_true<T, K>(self, field: FieldRef<E, T, K>) -> Self {
136        self.push_condition(field.id(), Operator::AlwaysTrue, Vec::new(), false)
137    }
138
139    #[must_use]
140    pub fn always_false<T, K>(self, field: FieldRef<E, T, K>) -> Self {
141        self.push_condition(field.id(), Operator::AlwaysFalse, Vec::new(), false)
142    }
143
144    #[must_use]
145    pub fn eq_ignore_case<K>(
146        self,
147        field: FieldRef<E, String, K>,
148        value: impl Into<String>,
149    ) -> Self {
150        self.text(field, Operator::Eq, value, true)
151    }
152
153    #[must_use]
154    pub fn ne_ignore_case<K>(
155        self,
156        field: FieldRef<E, String, K>,
157        value: impl Into<String>,
158    ) -> Self {
159        self.text(field, Operator::Ne, value, true)
160    }
161
162    #[must_use]
163    pub fn starts_with<K>(self, field: FieldRef<E, String, K>, value: impl Into<String>) -> Self {
164        self.text(field, Operator::StartWith, value, false)
165    }
166
167    #[must_use]
168    pub fn starts_with_ignore_case<K>(
169        self,
170        field: FieldRef<E, String, K>,
171        value: impl Into<String>,
172    ) -> Self {
173        self.text(field, Operator::StartWith, value, true)
174    }
175
176    #[must_use]
177    pub fn ends_with<K>(self, field: FieldRef<E, String, K>, value: impl Into<String>) -> Self {
178        self.text(field, Operator::EndWith, value, false)
179    }
180
181    #[must_use]
182    pub fn contains<K>(self, field: FieldRef<E, String, K>, value: impl Into<String>) -> Self {
183        self.text(field, Operator::Contain, value, false)
184    }
185
186    #[must_use]
187    pub fn contains_ignore_case<K>(
188        self,
189        field: FieldRef<E, String, K>,
190        value: impl Into<String>,
191    ) -> Self {
192        self.text(field, Operator::Contain, value, true)
193    }
194
195    #[must_use]
196    pub fn not_like<K>(self, field: FieldRef<E, String, K>, pattern: impl Into<String>) -> Self {
197        self.text(field, Operator::NotLike, pattern, false)
198    }
199
200    #[must_use]
201    pub fn or_like<K, I, S>(self, field: FieldRef<E, String, K>, patterns: I) -> Self
202    where
203        I: IntoIterator<Item = S>,
204        S: Into<String>,
205    {
206        self.push_condition(
207            field.id(),
208            Operator::OrLike,
209            patterns
210                .into_iter()
211                .map(|value| ScalarValue::Text(value.into()))
212                .collect(),
213            false,
214        )
215    }
216
217    #[must_use]
218    pub fn custom<T, K, I>(
219        self,
220        field: FieldRef<E, T, K>,
221        operator: CustomOperator,
222        values: I,
223    ) -> Self
224    where
225        T: IntoScalarValue,
226        I: IntoIterator<Item = T>,
227    {
228        self.push_condition(
229            field.id(),
230            Operator::Custom(operator),
231            values
232                .into_iter()
233                .map(IntoScalarValue::into_scalar_value)
234                .collect(),
235            false,
236        )
237    }
238
239    /// Typed custom input may differ from the field's returned Rust type.
240    #[must_use]
241    pub fn custom_values<T, K, V: IntoScalarValue>(
242        self,
243        field: FieldRef<E, T, K>,
244        operator: CustomOperator,
245        values: impl IntoIterator<Item = V>,
246    ) -> Self {
247        self.push_condition(
248            field.id(),
249            Operator::Custom(operator),
250            values
251                .into_iter()
252                .map(IntoScalarValue::into_scalar_value)
253                .collect(),
254            false,
255        )
256    }
257
258    fn list<T, K, I>(self, field: FieldRef<E, T, K>, operator: Operator, values: I) -> Self
259    where
260        T: IntoScalarValue,
261        I: IntoIterator<Item = T>,
262    {
263        self.push_condition(
264            field.id(),
265            operator,
266            values
267                .into_iter()
268                .map(IntoScalarValue::into_scalar_value)
269                .collect(),
270            false,
271        )
272    }
273
274    fn text<K>(
275        self,
276        field: FieldRef<E, String, K>,
277        operator: Operator,
278        value: impl Into<String>,
279        ignore_case: bool,
280    ) -> Self {
281        self.push_condition(
282            field.id(),
283            operator,
284            vec![ScalarValue::Text(value.into())],
285            ignore_case,
286        )
287    }
288}