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}