11#![ allow( missing_docs) ]
22
3+ use std:: borrow:: Borrow ;
4+
35use serde:: { Deserialize , Serialize } ;
46use serde_with:: skip_serializing_none;
7+ use typed_builder:: TypedBuilder ;
58
69use crate :: {
710 bson:: { rawdoc, Array , Bson , Document , RawDocumentBuf } ,
811 bson_util:: { get_or_prepend_id_field, replacement_document_check, update_document_check} ,
912 error:: Result ,
1013 options:: { UpdateModifications , WriteConcern } ,
1114 serde_util:: serialize_bool_or_true,
15+ Collection ,
1216 Namespace ,
1317} ;
1418
@@ -32,66 +36,205 @@ pub struct BulkWriteOptions {
3236#[ serde( untagged) ]
3337#[ non_exhaustive]
3438pub 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 ,
91228 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+ }
95238}
96239
97240pub ( crate ) enum OperationType {
@@ -103,34 +246,30 @@ pub(crate) enum OperationType {
103246impl WriteModel {
104247 pub ( crate ) fn namespace ( & self ) -> & Namespace {
105248 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 ,
112255 }
113256 }
114257
115258 pub ( crate ) fn operation_type ( & self ) -> OperationType {
116259 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 ,
122263 }
123264 }
124265
125266 /// Whether this operation should apply to all documents that match the filter. Returns None if
126267 /// the operation does not use a filter.
127268 pub ( crate ) fn multi ( & self ) -> Option < bool > {
128269 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 ,
134273 }
135274 }
136275
@@ -145,17 +284,19 @@ impl WriteModel {
145284 /// Returns the operation-specific fields that should be included in this model's entry in the
146285 /// ops array. Also returns an inserted ID if this is an insert operation.
147286 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+ {
149290 if let UpdateModifications :: Document ( update_document) = update {
150291 update_document_check ( update_document) ?;
151292 }
152- } else if let Self :: ReplaceOne { replacement, .. } = self {
293+ } else if let Self :: ReplaceOne ( ReplaceOneModel { replacement, .. } ) = self {
153294 replacement_document_check ( replacement) ?;
154295 }
155296
156297 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 ) ?;
159300 let inserted_id = get_or_prepend_id_field ( & mut insert_document) ?;
160301 ( rawdoc ! { "document" : insert_document } , Some ( inserted_id) )
161302 }
0 commit comments