1use serde_json::{json, Value};
22
23pub fn eq(value: impl Into<Value>) -> Value {
29 json!({"$eq": value.into()})
30}
31
32pub fn ne(value: impl Into<Value>) -> Value {
34 json!({"$ne": value.into()})
35}
36
37pub fn gt(value: impl Into<Value>) -> Value {
39 json!({"$gt": value.into()})
40}
41
42pub fn gte(value: impl Into<Value>) -> Value {
44 json!({"$gte": value.into()})
45}
46
47pub fn lt(value: impl Into<Value>) -> Value {
49 json!({"$lt": value.into()})
50}
51
52pub fn lte(value: impl Into<Value>) -> Value {
54 json!({"$lte": value.into()})
55}
56
57pub fn in_<I, V>(values: I) -> Value
59where
60 I: IntoIterator<Item = V>,
61 V: Into<Value>,
62{
63 let arr: Vec<Value> = values.into_iter().map(Into::into).collect();
64 json!({"$in": arr})
65}
66
67pub fn nin<I, V>(values: I) -> Value
69where
70 I: IntoIterator<Item = V>,
71 V: Into<Value>,
72{
73 let arr: Vec<Value> = values.into_iter().map(Into::into).collect();
74 json!({"$nin": arr})
75}
76
77pub fn exists(present: bool) -> Value {
79 json!({"$exists": present})
80}
81
82pub fn contains(substr: &str) -> Value {
88 json!({"$contains": substr})
89}
90
91pub fn icontains(substr: &str) -> Value {
93 json!({"$icontains": substr})
94}
95
96pub fn starts_with(prefix: &str) -> Value {
98 json!({"$startsWith": prefix})
99}
100
101pub fn ends_with(suffix: &str) -> Value {
103 json!({"$endsWith": suffix})
104}
105
106pub fn glob(pattern: &str) -> Value {
108 json!({"$glob": pattern})
109}
110
111pub fn regex(pattern: &str) -> Value {
113 json!({"$regex": pattern})
114}
115
116pub fn array_contains(value: impl Into<Value>) -> Value {
126 json!({"$arrayContains": value.into()})
127}
128
129pub fn array_contains_all<I, V>(values: I) -> Value
131where
132 I: IntoIterator<Item = V>,
133 V: Into<Value>,
134{
135 let arr: Vec<Value> = values.into_iter().map(Into::into).collect();
136 json!({"$arrayContainsAll": arr})
137}
138
139pub fn array_contains_any<I, V>(values: I) -> Value
141where
142 I: IntoIterator<Item = V>,
143 V: Into<Value>,
144{
145 let arr: Vec<Value> = values.into_iter().map(Into::into).collect();
146 json!({"$arrayContainsAny": arr})
147}
148
149pub fn and<I>(conditions: I) -> Value
155where
156 I: IntoIterator<Item = Value>,
157{
158 let arr: Vec<Value> = conditions.into_iter().collect();
159 json!({"$and": arr})
160}
161
162pub fn or<I>(conditions: I) -> Value
164where
165 I: IntoIterator<Item = Value>,
166{
167 let arr: Vec<Value> = conditions.into_iter().collect();
168 json!({"$or": arr})
169}
170
171#[cfg(test)]
172mod tests {
173 use super::*;
174 use serde_json::json;
175
176 #[test]
177 fn test_comparison_ops() {
178 assert_eq!(eq("hello"), json!({"$eq": "hello"}));
179 assert_eq!(gte(0.8_f64), json!({"$gte": 0.8}));
180 assert_eq!(lt(100_i64), json!({"$lt": 100}));
181 }
182
183 #[test]
184 fn test_string_ops() {
185 assert_eq!(contains("alice"), json!({"$contains": "alice"}));
186 assert_eq!(icontains("Alice"), json!({"$icontains": "Alice"}));
187 assert_eq!(starts_with("entity:"), json!({"$startsWith": "entity:"}));
188 assert_eq!(ends_with(":alice"), json!({"$endsWith": ":alice"}));
189 assert_eq!(glob("entity:*:alice"), json!({"$glob": "entity:*:alice"}));
190 assert_eq!(
191 regex("^entity:PERSON:"),
192 json!({"$regex": "^entity:PERSON:"})
193 );
194 }
195
196 #[test]
197 fn test_array_ops() {
198 assert_eq!(
199 array_contains("entity:PERSON:alice"),
200 json!({"$arrayContains": "entity:PERSON:alice"})
201 );
202 assert_eq!(
203 array_contains_all(["entity:PERSON:alice", "entity:PERSON:bob"]),
204 json!({"$arrayContainsAll": ["entity:PERSON:alice", "entity:PERSON:bob"]})
205 );
206 assert_eq!(
207 array_contains_any(["entity:PERSON:alice", "entity:PERSON:carol"]),
208 json!({"$arrayContainsAny": ["entity:PERSON:alice", "entity:PERSON:carol"]})
209 );
210 }
211
212 #[test]
213 fn test_logical_ops() {
214 let f = and([
215 json!({"importance": gte(0.8_f64)}),
216 json!({"tags": array_contains("entity:PERSON:alice")}),
217 ]);
218 assert_eq!(
219 f,
220 json!({"$and": [
221 {"importance": {"$gte": 0.8}},
222 {"tags": {"$arrayContains": "entity:PERSON:alice"}}
223 ]})
224 );
225 }
226
227 #[test]
228 fn test_in_nin() {
229 assert_eq!(in_(["a", "b", "c"]), json!({"$in": ["a", "b", "c"]}));
230 assert_eq!(nin([1_i64, 2_i64, 3_i64]), json!({"$nin": [1, 2, 3]}));
231 }
232
233 #[test]
234 fn test_exists() {
235 assert_eq!(exists(true), json!({"$exists": true}));
236 assert_eq!(exists(false), json!({"$exists": false}));
237 }
238}