mem0_rust/utils/
filters.rs

1//! Metadata filter utilities.
2
3use crate::models::{FilterCondition, FilterLogic, FilterOperator, Filters};
4
5/// Builder for creating filters
6pub struct FilterBuilder {
7    conditions: Vec<FilterCondition>,
8    logic: FilterLogic,
9}
10
11impl FilterBuilder {
12    /// Create a new filter builder with AND logic
13    pub fn new() -> Self {
14        Self {
15            conditions: Vec::new(),
16            logic: FilterLogic::And,
17        }
18    }
19
20    /// Create a new filter builder with OR logic
21    pub fn new_or() -> Self {
22        Self {
23            conditions: Vec::new(),
24            logic: FilterLogic::Or,
25        }
26    }
27
28    /// Add an equality condition
29    pub fn eq(mut self, field: impl Into<String>, value: impl Into<serde_json::Value>) -> Self {
30        self.conditions.push(FilterCondition {
31            field: field.into(),
32            operator: FilterOperator::Eq,
33            value: value.into(),
34        });
35        self
36    }
37
38    /// Add a not-equal condition
39    pub fn ne(mut self, field: impl Into<String>, value: impl Into<serde_json::Value>) -> Self {
40        self.conditions.push(FilterCondition {
41            field: field.into(),
42            operator: FilterOperator::Ne,
43            value: value.into(),
44        });
45        self
46    }
47
48    /// Add a greater-than condition
49    pub fn gt(mut self, field: impl Into<String>, value: impl Into<serde_json::Value>) -> Self {
50        self.conditions.push(FilterCondition {
51            field: field.into(),
52            operator: FilterOperator::Gt,
53            value: value.into(),
54        });
55        self
56    }
57
58    /// Add a greater-than-or-equal condition
59    pub fn gte(mut self, field: impl Into<String>, value: impl Into<serde_json::Value>) -> Self {
60        self.conditions.push(FilterCondition {
61            field: field.into(),
62            operator: FilterOperator::Gte,
63            value: value.into(),
64        });
65        self
66    }
67
68    /// Add a less-than condition
69    pub fn lt(mut self, field: impl Into<String>, value: impl Into<serde_json::Value>) -> Self {
70        self.conditions.push(FilterCondition {
71            field: field.into(),
72            operator: FilterOperator::Lt,
73            value: value.into(),
74        });
75        self
76    }
77
78    /// Add a less-than-or-equal condition
79    pub fn lte(mut self, field: impl Into<String>, value: impl Into<serde_json::Value>) -> Self {
80        self.conditions.push(FilterCondition {
81            field: field.into(),
82            operator: FilterOperator::Lte,
83            value: value.into(),
84        });
85        self
86    }
87
88    /// Add an "in list" condition
89    pub fn r#in(mut self, field: impl Into<String>, values: Vec<serde_json::Value>) -> Self {
90        self.conditions.push(FilterCondition {
91            field: field.into(),
92            operator: FilterOperator::In,
93            value: serde_json::Value::Array(values),
94        });
95        self
96    }
97
98    /// Add a "not in list" condition
99    pub fn nin(mut self, field: impl Into<String>, values: Vec<serde_json::Value>) -> Self {
100        self.conditions.push(FilterCondition {
101            field: field.into(),
102            operator: FilterOperator::Nin,
103            value: serde_json::Value::Array(values),
104        });
105        self
106    }
107
108    /// Add a contains condition (case-sensitive)
109    pub fn contains(mut self, field: impl Into<String>, value: impl Into<String>) -> Self {
110        self.conditions.push(FilterCondition {
111            field: field.into(),
112            operator: FilterOperator::Contains,
113            value: serde_json::Value::String(value.into()),
114        });
115        self
116    }
117
118    /// Add a contains condition (case-insensitive)
119    pub fn icontains(mut self, field: impl Into<String>, value: impl Into<String>) -> Self {
120        self.conditions.push(FilterCondition {
121            field: field.into(),
122            operator: FilterOperator::IContains,
123            value: serde_json::Value::String(value.into()),
124        });
125        self
126    }
127
128    /// Build the filters
129    pub fn build(self) -> Filters {
130        Filters {
131            conditions: self.conditions,
132            logic: self.logic,
133        }
134    }
135}
136
137impl Default for FilterBuilder {
138    fn default() -> Self {
139        Self::new()
140    }
141}
142
143#[cfg(test)]
144mod tests {
145    use super::*;
146
147    #[test]
148    fn test_filter_builder() {
149        let filters = FilterBuilder::new()
150            .eq("category", serde_json::json!("work"))
151            .gt("priority", serde_json::json!(5))
152            .build();
153
154        assert_eq!(filters.conditions.len(), 2);
155        assert_eq!(filters.logic, FilterLogic::And);
156    }
157
158    #[test]
159    fn test_filter_builder_or() {
160        let filters = FilterBuilder::new_or()
161            .eq("status", serde_json::json!("active"))
162            .eq("status", serde_json::json!("pending"))
163            .build();
164
165        assert_eq!(filters.logic, FilterLogic::Or);
166    }
167}