1
1
#![ allow( missing_docs) ]
2
2
3
+ use std:: borrow:: Borrow ;
4
+
3
5
use serde:: { Deserialize , Serialize } ;
4
6
use serde_with:: skip_serializing_none;
7
+ use typed_builder:: TypedBuilder ;
5
8
6
9
use crate :: {
7
10
bson:: { rawdoc, Array , Bson , Document , RawDocumentBuf } ,
8
11
bson_util:: { get_or_prepend_id_field, replacement_document_check, update_document_check} ,
9
12
error:: Result ,
10
13
options:: { UpdateModifications , WriteConcern } ,
11
14
serde_util:: serialize_bool_or_true,
15
+ Collection ,
12
16
Namespace ,
13
17
} ;
14
18
@@ -32,66 +36,205 @@ pub struct BulkWriteOptions {
32
36
#[ serde( untagged) ]
33
37
#[ non_exhaustive]
34
38
pub enum WriteModel {
35
- #[ non_exhaustive]
36
- InsertOne {
37
- #[ serde( skip) ]
38
- namespace : Namespace ,
39
- document : Document ,
40
- } ,
41
- #[ non_exhaustive]
42
- #[ serde( rename_all = "camelCase" ) ]
43
- UpdateOne {
44
- #[ serde( skip) ]
45
- namespace : Namespace ,
46
- filter : Document ,
47
- #[ serde( rename = "updateMods" ) ]
48
- update : UpdateModifications ,
49
- array_filters : Option < Array > ,
50
- collation : Option < Document > ,
51
- hint : Option < Bson > ,
52
- upsert : Option < bool > ,
53
- } ,
54
- #[ non_exhaustive]
55
- #[ serde( rename_all = "camelCase" ) ]
56
- UpdateMany {
57
- #[ serde( skip) ]
58
- namespace : Namespace ,
59
- filter : Document ,
60
- #[ serde( rename = "updateMods" ) ]
61
- update : UpdateModifications ,
62
- array_filters : Option < Array > ,
63
- collation : Option < Document > ,
64
- hint : Option < Bson > ,
65
- upsert : Option < bool > ,
66
- } ,
67
- #[ non_exhaustive]
68
- #[ serde( rename_all = "camelCase" ) ]
69
- ReplaceOne {
70
- #[ serde( skip) ]
71
- namespace : Namespace ,
72
- filter : Document ,
73
- #[ serde( rename = "updateMods" ) ]
74
- replacement : Document ,
75
- collation : Option < Document > ,
76
- hint : Option < Bson > ,
77
- upsert : Option < bool > ,
78
- } ,
79
- #[ non_exhaustive]
80
- DeleteOne {
81
- #[ serde( skip) ]
82
- namespace : Namespace ,
83
- filter : Document ,
84
- collation : Option < Document > ,
85
- hint : Option < Bson > ,
86
- } ,
87
- #[ non_exhaustive]
88
- DeleteMany {
89
- #[ serde( skip) ]
90
- namespace : Namespace ,
39
+ InsertOne ( InsertOneModel ) ,
40
+ UpdateOne ( UpdateOneModel ) ,
41
+ UpdateMany ( UpdateManyModel ) ,
42
+ ReplaceOne ( ReplaceOneModel ) ,
43
+ DeleteOne ( DeleteOneModel ) ,
44
+ DeleteMany ( DeleteManyModel ) ,
45
+ }
46
+
47
+ #[ skip_serializing_none]
48
+ #[ derive( Clone , Debug , Serialize , TypedBuilder ) ]
49
+ #[ cfg_attr( test, derive( Deserialize ) ) ]
50
+ #[ serde( rename_all = "camelCase" ) ]
51
+ #[ builder( field_defaults( default , setter( into) ) ) ]
52
+ #[ non_exhaustive]
53
+ pub struct InsertOneModel {
54
+ #[ serde( skip_serializing) ]
55
+ #[ builder( !default ) ]
56
+ pub namespace : Namespace ,
57
+
58
+ #[ builder( !default ) ]
59
+ pub document : Document ,
60
+ }
61
+
62
+ impl From < InsertOneModel > for WriteModel {
63
+ fn from ( model : InsertOneModel ) -> Self {
64
+ Self :: InsertOne ( model)
65
+ }
66
+ }
67
+
68
+ #[ skip_serializing_none]
69
+ #[ derive( Clone , Debug , Serialize , TypedBuilder ) ]
70
+ #[ cfg_attr( test, derive( Deserialize ) ) ]
71
+ #[ serde( rename_all = "camelCase" ) ]
72
+ #[ builder( field_defaults( default , setter( into) ) ) ]
73
+ #[ non_exhaustive]
74
+ pub struct UpdateOneModel {
75
+ #[ serde( skip_serializing) ]
76
+ #[ builder( !default ) ]
77
+ pub namespace : Namespace ,
78
+
79
+ #[ builder( !default ) ]
80
+ pub filter : Document ,
81
+
82
+ #[ serde( rename( serialize = "updateMods" ) ) ]
83
+ #[ builder( !default ) ]
84
+ pub update : UpdateModifications ,
85
+
86
+ pub array_filters : Option < Array > ,
87
+
88
+ pub collation : Option < Document > ,
89
+
90
+ pub hint : Option < Bson > ,
91
+
92
+ pub upsert : Option < bool > ,
93
+ }
94
+
95
+ impl From < UpdateOneModel > for WriteModel {
96
+ fn from ( model : UpdateOneModel ) -> Self {
97
+ Self :: UpdateOne ( model)
98
+ }
99
+ }
100
+
101
+ #[ skip_serializing_none]
102
+ #[ derive( Clone , Debug , Serialize , TypedBuilder ) ]
103
+ #[ cfg_attr( test, derive( Deserialize ) ) ]
104
+ #[ serde( rename_all = "camelCase" ) ]
105
+ #[ builder( field_defaults( default , setter( into) ) ) ]
106
+ #[ non_exhaustive]
107
+ pub struct UpdateManyModel {
108
+ #[ serde( skip_serializing) ]
109
+ #[ builder( !default ) ]
110
+ pub namespace : Namespace ,
111
+
112
+ #[ builder( !default ) ]
113
+ pub filter : Document ,
114
+
115
+ #[ serde( rename( serialize = "updateMods" ) ) ]
116
+ #[ builder( !default ) ]
117
+ pub update : UpdateModifications ,
118
+
119
+ pub array_filters : Option < Array > ,
120
+
121
+ pub collation : Option < Document > ,
122
+
123
+ pub hint : Option < Bson > ,
124
+
125
+ pub upsert : Option < bool > ,
126
+ }
127
+
128
+ impl From < UpdateManyModel > for WriteModel {
129
+ fn from ( model : UpdateManyModel ) -> Self {
130
+ Self :: UpdateMany ( model)
131
+ }
132
+ }
133
+
134
+ #[ skip_serializing_none]
135
+ #[ derive( Clone , Debug , Serialize , TypedBuilder ) ]
136
+ #[ cfg_attr( test, derive( Deserialize ) ) ]
137
+ #[ serde( rename_all = "camelCase" ) ]
138
+ #[ builder( field_defaults( default , setter( into) ) ) ]
139
+ #[ non_exhaustive]
140
+ pub struct ReplaceOneModel {
141
+ #[ serde( skip_serializing) ]
142
+ #[ builder( !default ) ]
143
+ pub namespace : Namespace ,
144
+
145
+ #[ builder( !default ) ]
146
+ pub filter : Document ,
147
+
148
+ #[ serde( rename( serialize = "updateMods" ) ) ]
149
+ #[ builder( !default ) ]
150
+ pub replacement : Document ,
151
+
152
+ pub collation : Option < Document > ,
153
+
154
+ pub hint : Option < Bson > ,
155
+
156
+ pub upsert : Option < bool > ,
157
+ }
158
+
159
+ impl From < ReplaceOneModel > for WriteModel {
160
+ fn from ( model : ReplaceOneModel ) -> Self {
161
+ Self :: ReplaceOne ( model)
162
+ }
163
+ }
164
+
165
+ #[ skip_serializing_none]
166
+ #[ derive( Clone , Debug , Serialize , TypedBuilder ) ]
167
+ #[ cfg_attr( test, derive( Deserialize ) ) ]
168
+ #[ serde( rename_all = "camelCase" ) ]
169
+ #[ builder( field_defaults( default , setter( into) ) ) ]
170
+ #[ non_exhaustive]
171
+ pub struct DeleteOneModel {
172
+ #[ serde( skip_serializing) ]
173
+ #[ builder( !default ) ]
174
+ pub namespace : Namespace ,
175
+
176
+ #[ builder( !default ) ]
177
+ pub filter : Document ,
178
+
179
+ pub collation : Option < Document > ,
180
+
181
+ pub hint : Option < Bson > ,
182
+ }
183
+
184
+ impl From < DeleteOneModel > for WriteModel {
185
+ fn from ( model : DeleteOneModel ) -> Self {
186
+ Self :: DeleteOne ( model)
187
+ }
188
+ }
189
+
190
+ #[ skip_serializing_none]
191
+ #[ derive( Clone , Debug , Serialize , TypedBuilder ) ]
192
+ #[ cfg_attr( test, derive( Deserialize ) ) ]
193
+ #[ serde( rename_all = "camelCase" ) ]
194
+ #[ builder( field_defaults( default , setter( into) ) ) ]
195
+ #[ non_exhaustive]
196
+ pub struct DeleteManyModel {
197
+ #[ serde( skip_serializing) ]
198
+ #[ builder( !default ) ]
199
+ pub namespace : Namespace ,
200
+
201
+ pub filter : Document ,
202
+
203
+ pub collation : Option < Document > ,
204
+
205
+ pub hint : Option < Bson > ,
206
+ }
207
+
208
+ impl From < DeleteManyModel > for WriteModel {
209
+ fn from ( model : DeleteManyModel ) -> Self {
210
+ Self :: DeleteMany ( model)
211
+ }
212
+ }
213
+
214
+ impl < T > Collection < T >
215
+ where
216
+ T : Send + Sync + Serialize ,
217
+ {
218
+ pub fn insert_one_model ( & self , document : impl Borrow < T > ) -> Result < InsertOneModel > {
219
+ let document = bson:: to_document ( document. borrow ( ) ) ?;
220
+ Ok ( InsertOneModel :: builder ( )
221
+ . namespace ( self . namespace ( ) )
222
+ . document ( document)
223
+ . build ( ) )
224
+ }
225
+
226
+ pub fn replace_one_model (
227
+ & self ,
91
228
filter : Document ,
92
- collation : Option < Document > ,
93
- hint : Option < Bson > ,
94
- } ,
229
+ replacement : impl Borrow < T > ,
230
+ ) -> Result < ReplaceOneModel > {
231
+ let replacement = bson:: to_document ( replacement. borrow ( ) ) ?;
232
+ Ok ( ReplaceOneModel :: builder ( )
233
+ . namespace ( self . namespace ( ) )
234
+ . filter ( filter)
235
+ . replacement ( replacement)
236
+ . build ( ) )
237
+ }
95
238
}
96
239
97
240
pub ( crate ) enum OperationType {
@@ -103,34 +246,30 @@ pub(crate) enum OperationType {
103
246
impl WriteModel {
104
247
pub ( crate ) fn namespace ( & self ) -> & Namespace {
105
248
match self {
106
- Self :: InsertOne { namespace , .. } => namespace,
107
- Self :: UpdateOne { namespace , .. } => namespace,
108
- Self :: UpdateMany { namespace , .. } => namespace,
109
- Self :: ReplaceOne { namespace , .. } => namespace,
110
- Self :: DeleteOne { namespace , .. } => namespace,
111
- Self :: DeleteMany { namespace , .. } => namespace,
249
+ Self :: InsertOne ( model ) => & model . namespace ,
250
+ Self :: UpdateOne ( model ) => & model . namespace ,
251
+ Self :: UpdateMany ( model ) => & model . namespace ,
252
+ Self :: ReplaceOne ( model ) => & model . namespace ,
253
+ Self :: DeleteOne ( model ) => & model . namespace ,
254
+ Self :: DeleteMany ( model ) => & model . namespace ,
112
255
}
113
256
}
114
257
115
258
pub ( crate ) fn operation_type ( & self ) -> OperationType {
116
259
match self {
117
- Self :: InsertOne { .. } => OperationType :: Insert ,
118
- Self :: UpdateOne { .. } | Self :: UpdateMany { .. } | Self :: ReplaceOne { .. } => {
119
- OperationType :: Update
120
- }
121
- Self :: DeleteOne { .. } | Self :: DeleteMany { .. } => OperationType :: Delete ,
260
+ Self :: InsertOne ( _) => OperationType :: Insert ,
261
+ Self :: UpdateOne ( _) | Self :: UpdateMany ( _) | Self :: ReplaceOne ( _) => OperationType :: Update ,
262
+ Self :: DeleteOne ( _) | Self :: DeleteMany ( _) => OperationType :: Delete ,
122
263
}
123
264
}
124
265
125
266
/// Whether this operation should apply to all documents that match the filter. Returns None if
126
267
/// the operation does not use a filter.
127
268
pub ( crate ) fn multi ( & self ) -> Option < bool > {
128
269
match self {
129
- Self :: UpdateMany { .. } | Self :: DeleteMany { .. } => Some ( true ) ,
130
- Self :: UpdateOne { .. } | Self :: ReplaceOne { .. } | Self :: DeleteOne { .. } => {
131
- Some ( false )
132
- }
133
- Self :: InsertOne { .. } => None ,
270
+ Self :: UpdateMany ( _) | Self :: DeleteMany ( _) => Some ( true ) ,
271
+ Self :: UpdateOne ( _) | Self :: ReplaceOne ( _) | Self :: DeleteOne ( _) => Some ( false ) ,
272
+ Self :: InsertOne ( _) => None ,
134
273
}
135
274
}
136
275
@@ -145,17 +284,19 @@ impl WriteModel {
145
284
/// Returns the operation-specific fields that should be included in this model's entry in the
146
285
/// ops array. Also returns an inserted ID if this is an insert operation.
147
286
pub ( crate ) fn get_ops_document_contents ( & self ) -> Result < ( RawDocumentBuf , Option < Bson > ) > {
148
- if let Self :: UpdateOne { update, .. } | Self :: UpdateMany { update, .. } = self {
287
+ if let Self :: UpdateOne ( UpdateOneModel { update, .. } )
288
+ | Self :: UpdateMany ( UpdateManyModel { update, .. } ) = self
289
+ {
149
290
if let UpdateModifications :: Document ( update_document) = update {
150
291
update_document_check ( update_document) ?;
151
292
}
152
- } else if let Self :: ReplaceOne { replacement, .. } = self {
293
+ } else if let Self :: ReplaceOne ( ReplaceOneModel { replacement, .. } ) = self {
153
294
replacement_document_check ( replacement) ?;
154
295
}
155
296
156
297
let ( mut model_document, inserted_id) = match self {
157
- Self :: InsertOne { document , .. } => {
158
- let mut insert_document = RawDocumentBuf :: from_document ( document) ?;
298
+ Self :: InsertOne ( model ) => {
299
+ let mut insert_document = RawDocumentBuf :: from_document ( & model . document ) ?;
159
300
let inserted_id = get_or_prepend_id_field ( & mut insert_document) ?;
160
301
( rawdoc ! { "document" : insert_document } , Some ( inserted_id) )
161
302
}
0 commit comments