1
- use std:: time:: Duration ;
1
+ use std:: { marker :: PhantomData , time:: Duration } ;
2
2
3
3
use bson:: Document ;
4
4
@@ -24,15 +24,17 @@ impl Database {
24
24
/// See the documentation [here](https://www.mongodb.com/docs/manual/aggregation/) for more
25
25
/// information on aggregations.
26
26
///
27
- /// `await` will return d[`Result<Cursor<Document>>`] or d[`Result<SessionCursor<Document>>`] if
28
- /// a `ClientSession` is provided.
27
+ /// `await` will return d[`Result<Cursor<Document>>`]. If a [`ClientSession`] was provided, the
28
+ /// returned cursor will be a [`SessionCursor`]. If [`with_type`](Aggregate::with_type) was
29
+ /// called, the returned cursor will be generic over the `T` specified.
29
30
#[ deeplink]
30
31
pub fn aggregate ( & self , pipeline : impl IntoIterator < Item = Document > ) -> Aggregate {
31
32
Aggregate {
32
33
target : AggregateTargetRef :: Database ( self ) ,
33
34
pipeline : pipeline. into_iter ( ) . collect ( ) ,
34
35
options : None ,
35
36
session : ImplicitSession ,
37
+ _phantom : PhantomData ,
36
38
}
37
39
}
38
40
}
@@ -46,15 +48,17 @@ where
46
48
/// See the documentation [here](https://www.mongodb.com/docs/manual/aggregation/) for more
47
49
/// information on aggregations.
48
50
///
49
- /// `await` will return d[`Result<Cursor<Document>>`] or d[`Result<SessionCursor<Document>>`] if
50
- /// a [`ClientSession`] is provided.
51
+ /// `await` will return d[`Result<Cursor<Document>>`]. If a [`ClientSession`] was provided, the
52
+ /// returned cursor will be a [`SessionCursor`]. If [`with_type`](Aggregate::with_type) was
53
+ /// called, the returned cursor will be generic over the `T` specified.
51
54
#[ deeplink]
52
55
pub fn aggregate ( & self , pipeline : impl IntoIterator < Item = Document > ) -> Aggregate {
53
56
Aggregate {
54
57
target : AggregateTargetRef :: Collection ( CollRef :: new ( self ) ) ,
55
58
pipeline : pipeline. into_iter ( ) . collect ( ) ,
56
59
options : None ,
57
60
session : ImplicitSession ,
61
+ _phantom : PhantomData ,
58
62
}
59
63
}
60
64
}
@@ -66,8 +70,10 @@ impl crate::sync::Database {
66
70
/// See the documentation [here](https://www.mongodb.com/docs/manual/aggregation/) for more
67
71
/// information on aggregations.
68
72
///
69
- /// [`run`](Aggregate::run) will return d[`Result<crate::sync::Cursor<Document>>`] or
70
- /// d[`Result<crate::sync::SessionCursor<Document>>`] if a [`ClientSession`] is provided.
73
+ /// [`run`](Aggregate::run) will return d[Result<crate::sync::Cursor<Document>>`]. If a
74
+ /// [`crate::sync::ClientSession`] was provided, the returned cursor will be a
75
+ /// [`crate::sync::SessionCursor`]. If [`with_type`](Aggregate::with_type) was called, the
76
+ /// returned cursor will be generic over the `T` specified.
71
77
#[ deeplink]
72
78
pub fn aggregate ( & self , pipeline : impl IntoIterator < Item = Document > ) -> Aggregate {
73
79
self . async_database . aggregate ( pipeline)
84
90
/// See the documentation [here](https://www.mongodb.com/docs/manual/aggregation/) for more
85
91
/// information on aggregations.
86
92
///
87
- /// [`run`](Aggregate::run) will return d[`Result<crate::sync::Cursor<Document>>`] or
88
- /// d[`Result<crate::sync::SessionCursor<Document>>`] if a `ClientSession` is provided.
93
+ /// [`run`](Aggregate::run) will return d[Result<crate::sync::Cursor<Document>>`]. If a
94
+ /// `crate::sync::ClientSession` was provided, the returned cursor will be a
95
+ /// `crate::sync::SessionCursor`. If [`with_type`](Aggregate::with_type) was called, the
96
+ /// returned cursor will be generic over the `T` specified.
89
97
#[ deeplink]
90
98
pub fn aggregate ( & self , pipeline : impl IntoIterator < Item = Document > ) -> Aggregate {
91
99
self . async_collection . aggregate ( pipeline)
@@ -95,14 +103,15 @@ where
95
103
/// Run an aggregation operation. Construct with [`Database::aggregate`] or
96
104
/// [`Collection::aggregate`].
97
105
#[ must_use]
98
- pub struct Aggregate < ' a , Session = ImplicitSession > {
106
+ pub struct Aggregate < ' a , Session = ImplicitSession , T = Document > {
99
107
target : AggregateTargetRef < ' a > ,
100
108
pipeline : Vec < Document > ,
101
109
options : Option < AggregateOptions > ,
102
110
session : Session ,
111
+ _phantom : PhantomData < T > ,
103
112
}
104
113
105
- impl < ' a , Session > Aggregate < ' a , Session > {
114
+ impl < ' a , Session , T > Aggregate < ' a , Session , T > {
106
115
option_setters ! ( options: AggregateOptions ;
107
116
allow_disk_use: bool ,
108
117
batch_size: u32 ,
@@ -130,15 +139,50 @@ impl<'a> Aggregate<'a, ImplicitSession> {
130
139
pipeline : self . pipeline ,
131
140
options : self . options ,
132
141
session : ExplicitSession ( value. into ( ) ) ,
142
+ _phantom : PhantomData ,
133
143
}
134
144
}
135
145
}
136
146
137
- #[ action_impl( sync = crate :: sync:: Cursor <Document >) ]
138
- impl < ' a > Action for Aggregate < ' a , ImplicitSession > {
147
+ impl < ' a , Session > Aggregate < ' a , Session , Document > {
148
+ /// Use the provided type for the returned cursor.
149
+ ///
150
+ /// ```rust
151
+ /// # use futures_util::TryStreamExt;
152
+ /// # use mongodb::{bson::Document, error::Result, Cursor, Database};
153
+ /// # use serde::Deserialize;
154
+ /// # async fn run() -> Result<()> {
155
+ /// # let database: Database = todo!();
156
+ /// # let pipeline: Vec<Document> = todo!();
157
+ /// #[derive(Deserialize)]
158
+ /// struct PipelineOutput {
159
+ /// len: usize,
160
+ /// }
161
+ ///
162
+ /// let aggregate_cursor = database
163
+ /// .aggregate(pipeline)
164
+ /// .with_type::<PipelineOutput>()
165
+ /// .await?;
166
+ /// let aggregate_results: Vec<PipelineOutput> = aggregate_cursor.try_collect().await?;
167
+ /// # Ok(())
168
+ /// # }
169
+ /// ```
170
+ pub fn with_type < T > ( self ) -> Aggregate < ' a , Session , T > {
171
+ Aggregate {
172
+ target : self . target ,
173
+ pipeline : self . pipeline ,
174
+ options : self . options ,
175
+ session : self . session ,
176
+ _phantom : PhantomData ,
177
+ }
178
+ }
179
+ }
180
+
181
+ #[ action_impl( sync = crate :: sync:: Cursor <T >) ]
182
+ impl < ' a , T > Action for Aggregate < ' a , ImplicitSession , T > {
139
183
type Future = AggregateFuture ;
140
184
141
- async fn execute ( mut self ) -> Result < Cursor < Document > > {
185
+ async fn execute ( mut self ) -> Result < Cursor < T > > {
142
186
resolve_options ! (
143
187
self . target,
144
188
self . options,
0 commit comments