deeb/database/query.rs
1use serde_json::Value;
2
3use crate::Entity;
4
5#[derive(Debug, Clone, PartialEq)]
6pub struct Key(String);
7
8impl std::fmt::Display for Key {
9 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
10 write!(f, "{}", self.0)
11 }
12}
13
14impl From<&str> for Key {
15 fn from(s: &str) -> Self {
16 Self(s.to_string())
17 }
18}
19
20#[derive(Debug, Clone, PartialEq)]
21pub enum Query {
22 Eq(Key, Value),
23 Ne(Key, Value),
24 Like(Key, String),
25 Lt(Key, Value),
26 Lte(Key, Value),
27 Gt(Key, Value),
28 Gte(Key, Value),
29 And(Vec<Query>),
30 Or(Vec<Query>),
31 Associated(Entity, Box<Query>),
32 All,
33}
34
35impl Query {
36 /// Create a new query that matches documents based on exact match.
37 ///
38 /// ```
39 /// use deeb::*;
40 ///
41 /// let query = Query::eq("name", "John");
42 /// ```
43 #[allow(dead_code)]
44 pub fn eq<K, V>(key: K, value: V) -> Self
45 where
46 K: Into<Key>,
47 V: Into<Value>,
48 {
49 Self::Eq(key.into(), value.into())
50 }
51
52 /// Create a new query that matches documents based on not equal match.
53 ///
54 /// ```
55 /// use deeb::*;
56 /// let query = Query::ne("name", "John");
57 /// ```
58 #[allow(dead_code)]
59 pub fn ne<K, V>(key: K, value: V) -> Self
60 where
61 K: Into<Key>,
62 V: Into<Value>,
63 {
64 Self::Ne(key.into(), value.into())
65 }
66
67 /// Create a new query that matches documents based on multiple conditions.
68 ///
69 /// ```
70 /// use deeb::*;
71 ///
72 /// let query = Query::and(vec![
73 /// Query::eq("name", "John"),
74 /// Query::eq("age", 30),
75 /// Query::eq("city", "New York"),
76 /// ]);
77 /// ```
78 #[allow(dead_code)]
79 pub fn and(queries: Vec<Query>) -> Self {
80 Self::And(queries)
81 }
82
83 /// Create a new query that matches documents based on multiple conditions.
84 ///
85 /// ```
86 /// use deeb::*;
87 ///
88 /// let query = Query::or(vec![
89 /// Query::eq("name", "John"),
90 /// Query::eq("age", 30),
91 /// Query::eq("city", "New York"),
92 /// ]);
93 /// ```
94 #[allow(dead_code)]
95 pub fn or(queries: Vec<Query>) -> Self {
96 Self::Or(queries)
97 }
98
99 /// Create a new query that matches documents based on like match.
100 ///
101 /// ```
102 /// use deeb::*;
103 /// let query = Query::like("name", "John");
104 /// ```
105 #[allow(dead_code)]
106 pub fn like<K, V>(key: K, value: V) -> Self
107 where
108 K: Into<Key>,
109 V: Into<String>,
110 {
111 Self::Like(key.into(), value.into())
112 }
113
114 /// Create a new query that matches documents based on less than match.
115 ///
116 /// ```
117 /// use deeb::*;
118 /// let query = Query::lt("age", 30);
119 /// ```
120 #[allow(dead_code)]
121 pub fn lt<K, V>(key: K, value: V) -> Self
122 where
123 K: Into<Key>,
124 V: Into<Value>,
125 {
126 Self::Lt(key.into(), value.into())
127 }
128
129 /// Create a new query that matches documents based on less than or equal match.
130 ///
131 /// ```
132 /// use deeb::*;
133 /// let query = Query::lte("age", 30);
134 /// ```
135 #[allow(dead_code)]
136 pub fn lte<K, V>(key: K, value: V) -> Self
137 where
138 K: Into<Key>,
139 V: Into<Value>,
140 {
141 Self::Lte(key.into(), value.into())
142 }
143
144 /// Create a new query that matches documents based on greater than match.
145 ///
146 /// ```
147 /// use deeb::*;
148 /// let query = Query::gt("age", 30);
149 /// ```
150 #[allow(dead_code)]
151 pub fn gt<K, V>(key: K, value: V) -> Self
152 where
153 K: Into<Key>,
154 V: Into<Value>,
155 {
156 Self::Gt(key.into(), value.into())
157 }
158
159 /// Create a new query that matches documents based on greater than or equal match.
160 ///
161 /// ```
162 /// use deeb::*;
163 /// let query = Query::gte("age", 30);
164 /// ```
165 #[allow(dead_code)]
166 pub fn gte<K, V>(key: K, value: V) -> Self
167 where
168 K: Into<Key>,
169 V: Into<Value>,
170 {
171 Self::Gte(key.into(), value.into())
172 }
173
174 /// Create a new query that matches all documents.
175 /// ```
176 /// use deeb::*;
177 /// let query = Query::all();
178 /// ```
179 #[allow(dead_code)]
180 pub fn all() -> Self {
181 Self::All
182 }
183
184 /// Create a new query that matches documents based on associated entity.
185 /// ```
186 /// use deeb::*;
187 /// let user = Entity::new("user");
188 /// let comment = Entity::new("comment");
189 /// let query = Query::associated(comment, Query::eq("user_id", 1));
190 /// ```
191 #[allow(dead_code)]
192 pub fn associated(entity: Entity, query: Query) -> Self {
193 Self::Associated(entity, Box::new(query))
194 }
195
196 fn get_kv(&self, value: &Value, key: &str) -> Option<(Key, Value)> {
197 if !key.contains('.') {
198 let value = value.get(key);
199 if value.is_none() {
200 return None;
201 }
202 return Some((Key(key.to_string()), value.cloned().unwrap()));
203 }
204 let mut keys = key.split('.').peekable();
205 let mut value = value;
206 let mut current_key = None;
207 while let Some(key) = keys.next() {
208 current_key = Some(key.to_string());
209 if !value.is_object() {
210 break;
211 }
212 if let Some(nested) = value.get(key) {
213 value = nested;
214 } else {
215 return None;
216 }
217 }
218 Some((Key(current_key.unwrap()), value.clone()))
219 }
220
221 pub fn associated_entities(&self) -> Vec<Entity> {
222 let mut entities = vec![];
223 match self {
224 Self::Associated(entity, query) => {
225 entities.push(entity.clone());
226 entities.append(&mut query.associated_entities());
227 }
228 Self::And(queries) => {
229 for query in queries {
230 entities.append(&mut query.associated_entities());
231 }
232 }
233 Self::Or(queries) => {
234 for query in queries {
235 entities.append(&mut query.associated_entities());
236 }
237 }
238 _ => {}
239 }
240 entities
241 }
242
243 /// Check if the query matches the value.
244 ///
245 /// ```
246 /// use deeb::*;
247 /// use serde_json::json;
248 /// let query = Query::eq("name", "John");
249 /// let value = json!({"name": "John"});
250 /// let is_match = query.matches(&value).unwrap();
251 /// assert_eq!(is_match, true);
252 /// ```
253 pub fn matches(&self, value: &Value) -> Result<bool, anyhow::Error> {
254 let is_match = match self {
255 Self::Eq(key, query_value) => {
256 let kv = self.get_kv(value, &key.0);
257 if let Some((kv_key, value)) = kv {
258 if value.is_array() {
259 let value = value.as_array().unwrap();
260 for v in value {
261 if v.is_object() {
262 let v = v.as_object().unwrap();
263 for (k, v) in v.iter() {
264 if v == query_value && k == &kv_key.to_string() {
265 return Ok(true);
266 }
267 }
268 }
269 if v == query_value {
270 return Ok(true);
271 }
272 }
273 return Ok(false);
274 }
275 value == query_value.clone()
276 } else {
277 false
278 }
279 }
280 Self::Ne(key, query_value) => {
281 let kv = self.get_kv(value, &key.0);
282 if let Some((_key, value)) = kv {
283 if value.is_array() {
284 let value = value.as_array().unwrap();
285 for v in value {
286 if v.is_object() {
287 let v = v.as_object().unwrap();
288 for (k, v) in v.iter() {
289 if v == query_value && k == &key.0 {
290 return Ok(false);
291 }
292 }
293 return Ok(true);
294 }
295 if v == query_value {
296 return Ok(false);
297 }
298 }
299 }
300 value != query_value.clone()
301 } else {
302 false
303 }
304 }
305 Self::Like(key, query_value) => {
306 let kv = self.get_kv(value, &key.0);
307 if let Some((key, value)) = kv {
308 if value.is_array() {
309 let value = value.as_array().unwrap();
310 for v in value {
311 if v.is_object() {
312 let v = v.as_object().unwrap();
313 for (k, v) in v.iter() {
314 if let Some(value) = v.as_str() {
315 if value.contains(query_value) && k == &key.to_string() {
316 return Ok(true);
317 }
318 }
319 }
320 }
321 if let Some(value) = v.as_str() {
322 if value.contains(query_value) {
323 return Ok(true);
324 }
325 }
326 }
327 return Ok(false);
328 }
329 if let Some(value) = value.as_str() {
330 value.contains(query_value)
331 } else {
332 false
333 }
334 } else {
335 false
336 }
337 }
338 Self::Lt(key, query_value) => {
339 let kv = self.get_kv(value, &key.0);
340 if let Some((key, value)) = kv {
341 // Handle Array
342 if value.is_array() {
343 let value = value.as_array().unwrap();
344 for v in value {
345 if v.is_object() {
346 let v = v.as_object().unwrap();
347 for (k, v) in v.iter() {
348 if let Some(value) = v.as_f64() {
349 let query_value = query_value.as_f64();
350 if query_value.is_none() {
351 continue;
352 }
353 let is_lt = value < query_value.unwrap() && k == &key.0;
354 if is_lt {
355 return Ok(true);
356 }
357 }
358 }
359 }
360 if let Some(value) = v.as_f64() {
361 let query_value = query_value.as_f64();
362 if query_value.is_none() {
363 continue;
364 }
365 let is_lt = value < query_value.unwrap();
366 if is_lt {
367 return Ok(true);
368 }
369 }
370 }
371 return Ok(false);
372 }
373 // Handle primitive types
374 if let Some(value) = value.as_f64() {
375 let query_value = query_value.as_f64();
376 match query_value {
377 Some(query_value) => value < query_value,
378 None => false,
379 }
380 } else if let Some(value) = value.as_i64() {
381 let query_value = query_value.as_i64();
382 match query_value {
383 Some(query_value) => value < query_value,
384 None => false,
385 }
386 } else if let Some(value) = value.as_u64() {
387 let query_value = query_value.as_u64();
388 match query_value {
389 Some(query_value) => value < query_value,
390 None => false,
391 }
392 } else {
393 false
394 }
395 } else {
396 false
397 }
398 }
399 Self::Lte(key, query_value) => {
400 let kv = self.get_kv(value, &key.0);
401 if let Some((key, value)) = kv {
402 // Handle Array
403 if value.is_array() {
404 let value = value.as_array().unwrap();
405 for v in value {
406 if v.is_object() {
407 let v = v.as_object().unwrap();
408 for (k, v) in v.iter() {
409 if let Some(value) = v.as_f64() {
410 let query_value = query_value.as_f64();
411 if query_value.is_none() {
412 continue;
413 }
414 let is_lte = value <= query_value.unwrap() && k == &key.0;
415 if is_lte {
416 return Ok(true);
417 }
418 }
419 }
420 }
421 if let Some(value) = v.as_f64() {
422 let query_value = query_value.as_f64();
423 if query_value.is_none() {
424 continue;
425 }
426 let is_lte = value <= query_value.unwrap();
427 if is_lte {
428 return Ok(true);
429 }
430 }
431 }
432 return Ok(false);
433 }
434
435 // Handle Primitivves
436 if let Some(value) = value.as_f64() {
437 let query_value = query_value.as_f64();
438 match query_value {
439 Some(query_value) => return Ok(value <= query_value),
440 None => return Ok(false),
441 }
442 } else if let Some(value) = value.as_i64() {
443 let query_value = query_value.as_i64();
444 match query_value {
445 Some(query_value) => return Ok(value <= query_value),
446 None => return Ok(false),
447 }
448 } else if let Some(value) = value.as_u64() {
449 let query_value = query_value.as_u64();
450 match query_value {
451 Some(query_value) => return Ok(value <= query_value),
452 None => return Ok(false),
453 }
454 } else {
455 return Ok(false);
456 }
457 } else {
458 return Ok(false);
459 }
460 }
461 Self::Gt(key, query_value) => {
462 let kv = self.get_kv(value, &key.0);
463 if let Some((key, value)) = kv {
464 // handle array
465 if value.is_array() {
466 let value = value.as_array().unwrap();
467 for v in value {
468 if v.is_object() {
469 let v = v.as_object().unwrap();
470 for (k, v) in v.iter() {
471 if let Some(value) = v.as_f64() {
472 let query_value = query_value.as_f64();
473 match query_value {
474 Some(query_value) => {
475 return Ok(value > query_value && k == &key.0)
476 }
477 None => return Ok(false),
478 };
479 }
480 }
481 return Ok(false);
482 }
483 if let Some(value) = v.as_f64() {
484 let query_value = query_value.as_f64();
485 let is_gt = value > query_value.unwrap();
486 if is_gt {
487 return Ok(true);
488 }
489 }
490 }
491 return Ok(false);
492 }
493
494 // handle primitives
495 if let Some(value) = value.as_f64() {
496 let query_value = query_value.as_f64();
497 match query_value {
498 Some(query_value) => return Ok(value > query_value),
499 None => return Ok(false),
500 }
501 } else if let Some(value) = value.as_i64() {
502 let query_value = query_value.as_i64();
503 match query_value {
504 Some(query_value) => return Ok(value > query_value),
505 None => return Ok(false),
506 }
507 } else if let Some(value) = value.as_u64() {
508 let query_value = query_value.as_u64();
509 match query_value {
510 Some(query_value) => return Ok(value > query_value),
511 None => return Ok(false),
512 }
513 } else {
514 return Ok(false);
515 }
516 } else {
517 return Ok(false);
518 }
519 }
520 Self::Gte(key, query_value) => {
521 let kv = self.get_kv(value, &key.0);
522 if let Some((key, value)) = kv {
523 // handle array
524 if value.is_array() {
525 let value = value.as_array().unwrap();
526 for v in value {
527 println!("V: {:?}", v);
528 if v.is_object() {
529 let v = v.as_object().unwrap();
530 for (k, v) in v.iter() {
531 if let Some(value) = v.as_f64() {
532 let query_value = query_value.as_f64();
533 match query_value {
534 Some(query_value) => {
535 return Ok(value >= query_value && k == &key.0)
536 }
537 None => return Ok(false),
538 };
539 }
540 }
541 return Ok(false);
542 }
543 if let Some(value) = v.as_f64() {
544 let query_value = query_value.as_f64();
545 if query_value.is_none() {
546 continue;
547 }
548 let is_gte = value >= query_value.unwrap();
549 if is_gte {
550 return Ok(true);
551 }
552 }
553 }
554 return Ok(false);
555 }
556
557 // handle primitives
558 if let Some(value) = value.as_f64() {
559 let query_value = query_value.as_f64();
560 match query_value {
561 Some(query_value) => return Ok(value >= query_value),
562 None => return Ok(false),
563 }
564 } else if let Some(value) = value.as_i64() {
565 let query_value = query_value.as_i64();
566 match query_value {
567 Some(query_value) => return Ok(value >= query_value),
568 None => return Ok(false),
569 }
570 } else if let Some(value) = value.as_u64() {
571 let query_value = query_value.as_u64();
572 match query_value {
573 Some(query_value) => return Ok(value >= query_value),
574 None => return Ok(false),
575 }
576 } else {
577 return Ok(false);
578 }
579 } else {
580 return Ok(false);
581 }
582 }
583 Self::And(queries) => queries
584 .iter()
585 .all(|query| query.matches(value).unwrap_or_else(|_| false)),
586 Self::Or(queries) => queries
587 .iter()
588 .any(|query| query.matches(value).unwrap_or_else(|_| false)),
589 Self::Associated(_entity, query) => {
590 let is_match = query.matches(value).unwrap_or_else(|_| false);
591 is_match
592 }
593 Self::All => true,
594 };
595 Ok(is_match)
596 }
597}