vantage_mongodb/
operation.rs1use bson::{Bson, doc};
10use vantage_expressions::Expressive;
11
12use crate::condition::MongoCondition;
13use crate::types::{AnyMongoType, MongoType};
14
15fn field_name<T>(expr: &(impl Expressive<T> + ?Sized)) -> String {
16 expr.expr().template.clone()
17}
18
19fn to_bson_val(value: impl Into<AnyMongoType>) -> Bson {
20 let any: AnyMongoType = value.into();
21 any.to_bson()
22}
23
24fn negate(cond: MongoCondition) -> MongoCondition {
27 match cond {
28 MongoCondition::Doc(doc) => {
29 let mut negated = bson::Document::new();
30 for (key, val) in doc {
31 match val {
32 Bson::Document(inner) => {
33 negated.insert(key, doc! { "$not": inner });
34 }
35 other => {
36 negated.insert(key, doc! { "$not": { "$eq": other } });
37 }
38 }
39 }
40 MongoCondition::Doc(negated)
41 }
42 MongoCondition::And(conditions) => {
43 MongoCondition::And(conditions.into_iter().map(negate).collect())
44 }
45 other => other,
47 }
48}
49
50pub trait MongoOperation<T>: Expressive<T> {
53 fn eq(&self, value: impl Into<AnyMongoType>) -> MongoCondition
55 where
56 Self: Sized,
57 {
58 MongoCondition::Doc(doc! { field_name(self): { "$eq": to_bson_val(value) } })
59 }
60
61 fn ne(&self, value: impl Into<AnyMongoType>) -> MongoCondition
63 where
64 Self: Sized,
65 {
66 MongoCondition::Doc(doc! { field_name(self): { "$ne": to_bson_val(value) } })
67 }
68
69 fn gt(&self, value: impl Into<AnyMongoType>) -> MongoCondition
71 where
72 Self: Sized,
73 {
74 MongoCondition::Doc(doc! { field_name(self): { "$gt": to_bson_val(value) } })
75 }
76
77 fn gte(&self, value: impl Into<AnyMongoType>) -> MongoCondition
79 where
80 Self: Sized,
81 {
82 MongoCondition::Doc(doc! { field_name(self): { "$gte": to_bson_val(value) } })
83 }
84
85 fn lt(&self, value: impl Into<AnyMongoType>) -> MongoCondition
87 where
88 Self: Sized,
89 {
90 MongoCondition::Doc(doc! { field_name(self): { "$lt": to_bson_val(value) } })
91 }
92
93 fn lte(&self, value: impl Into<AnyMongoType>) -> MongoCondition
95 where
96 Self: Sized,
97 {
98 MongoCondition::Doc(doc! { field_name(self): { "$lte": to_bson_val(value) } })
99 }
100
101 fn in_<I, V>(&self, values: I) -> MongoCondition
103 where
104 Self: Sized,
105 I: IntoIterator<Item = V>,
106 V: Into<AnyMongoType>,
107 {
108 let arr: Vec<Bson> = values.into_iter().map(to_bson_val).collect();
109 MongoCondition::Doc(doc! { field_name(self): { "$in": arr } })
110 }
111
112 fn is_null(&self) -> MongoCondition
114 where
115 Self: Sized,
116 {
117 MongoCondition::Doc(doc! { field_name(self): Bson::Null })
118 }
119
120 fn is_not_null(&self) -> MongoCondition
122 where
123 Self: Sized,
124 {
125 MongoCondition::Doc(doc! { field_name(self): { "$ne": Bson::Null } })
126 }
127}
128
129impl<T, S: Expressive<T>> MongoOperation<T> for S {}
130
131impl Expressive<AnyMongoType> for MongoCondition {
134 fn expr(&self) -> vantage_expressions::Expression<AnyMongoType> {
135 vantage_expressions::Expression::new(format!("{:?}", self), vec![])
136 }
137}
138
139impl MongoCondition {
140 pub fn eq_bool(&self, value: bool) -> MongoCondition {
142 if value {
143 self.clone()
144 } else {
145 negate(self.clone())
146 }
147 }
148
149 pub fn ne_bool(&self, value: bool) -> MongoCondition {
151 if value {
152 negate(self.clone())
153 } else {
154 self.clone()
155 }
156 }
157}