Skip to main content

vantage_mongodb/select/impls/
selectable.rs

1//! Selectable<AnyMongoType, MongoCondition> implementation for MongoSelect.
2
3use vantage_expressions::traits::selectable::SourceRef;
4use vantage_expressions::{Expression, Expressive, ExpressiveEnum, Order, Selectable};
5
6use crate::condition::MongoCondition;
7use crate::select::MongoSelect;
8use crate::types::AnyMongoType;
9
10impl Selectable<AnyMongoType, MongoCondition> for MongoSelect {
11    fn add_source(&mut self, source: impl Into<SourceRef<AnyMongoType>>, _alias: Option<String>) {
12        let source_ref = source.into().into_expressive_enum();
13        if let ExpressiveEnum::Scalar(val) = source_ref
14            && let Some(name) = val.try_get::<String>()
15        {
16            self.collection = Some(name);
17        }
18    }
19
20    fn add_field(&mut self, field: impl Into<String>) {
21        self.fields.push(field.into());
22    }
23
24    fn add_expression(&mut self, _expression: impl Expressive<AnyMongoType>) {
25        // MongoDB projections don't support arbitrary expressions in find().
26    }
27
28    fn add_where_condition(&mut self, condition: impl Into<MongoCondition>) {
29        self.conditions.push(condition.into());
30    }
31
32    fn set_distinct(&mut self, distinct: bool) {
33        self.distinct = distinct;
34    }
35
36    fn add_order_by(&mut self, order: impl Into<MongoCondition>, direction: Order) {
37        // Convention: a MongoCondition::Doc with a single key → use that key.
38        // The direction from the Order param overrides whatever value is in the doc.
39        let cond = order.into();
40        if let MongoCondition::Doc(doc) = &cond
41            && let Some((key, _)) = doc.iter().next()
42        {
43            let dir = if direction.ascending { 1 } else { -1 };
44            self.sort.push((key.to_string(), dir));
45        }
46    }
47
48    fn add_group_by(&mut self, expression: impl Expressive<AnyMongoType>) {
49        let preview = expression.preview();
50        self.group_by.push(preview);
51    }
52
53    fn set_limit(&mut self, limit: Option<i64>, skip: Option<i64>) {
54        self.limit = limit;
55        self.skip = skip;
56    }
57
58    fn clear_fields(&mut self) {
59        self.fields.clear();
60    }
61
62    fn clear_where_conditions(&mut self) {
63        self.conditions.clear();
64    }
65
66    fn clear_order_by(&mut self) {
67        self.sort.clear();
68    }
69
70    fn clear_group_by(&mut self) {
71        self.group_by.clear();
72    }
73
74    fn has_fields(&self) -> bool {
75        !self.fields.is_empty()
76    }
77
78    fn has_where_conditions(&self) -> bool {
79        !self.conditions.is_empty()
80    }
81
82    fn has_order_by(&self) -> bool {
83        !self.sort.is_empty()
84    }
85
86    fn has_group_by(&self) -> bool {
87        !self.group_by.is_empty()
88    }
89
90    fn is_distinct(&self) -> bool {
91        self.distinct
92    }
93
94    fn get_limit(&self) -> Option<i64> {
95        self.limit
96    }
97
98    fn get_skip(&self) -> Option<i64> {
99        self.skip
100    }
101
102    fn as_field(&self, _field: impl Into<String>) -> Expression<AnyMongoType> {
103        todo!("as_field not yet implemented for MongoDB")
104    }
105
106    fn as_count(&self) -> Expression<AnyMongoType> {
107        let coll = self.collection.as_deref().unwrap_or("?");
108        Expression::new(format!("db.{}.countDocuments()", coll), vec![])
109    }
110
111    fn as_sum(&self, column: impl Expressive<AnyMongoType>) -> Expression<AnyMongoType> {
112        let coll = self.collection.as_deref().unwrap_or("?");
113        Expression::new(
114            format!("db.{}.aggregate($sum: {})", coll, column.preview()),
115            vec![],
116        )
117    }
118
119    fn as_max(&self, column: impl Expressive<AnyMongoType>) -> Expression<AnyMongoType> {
120        let coll = self.collection.as_deref().unwrap_or("?");
121        Expression::new(
122            format!("db.{}.aggregate($max: {})", coll, column.preview()),
123            vec![],
124        )
125    }
126
127    fn as_min(&self, column: impl Expressive<AnyMongoType>) -> Expression<AnyMongoType> {
128        let coll = self.collection.as_deref().unwrap_or("?");
129        Expression::new(
130            format!("db.{}.aggregate($min: {})", coll, column.preview()),
131            vec![],
132        )
133    }
134}