1use std::{borrow::Borrow, time::Duration};
2
3use crate::bson::{Bson, Document, RawDocumentBuf};
4use serde::{de::DeserializeOwned, Serialize};
5
6use crate::{
7 coll::options::{
8 FindOneAndDeleteOptions,
9 FindOneAndReplaceOptions,
10 FindOneAndUpdateOptions,
11 Hint,
12 ReturnDocument,
13 UpdateModifications,
14 },
15 collation::Collation,
16 error::Result,
17 operation::{
18 find_and_modify::options::{FindAndModifyOptions, Modification},
19 FindAndModify as Op,
20 UpdateOrReplace,
21 },
22 options::WriteConcern,
23 ClientSession,
24 Collection,
25};
26
27use super::{action_impl, deeplink, export_doc, option_setters, options_doc};
28
29impl<T: DeserializeOwned + Send + Sync> Collection<T> {
30 async fn find_and_modify(
31 &self,
32 filter: Document,
33 modification: Modification,
34 options: Option<FindAndModifyOptions>,
35 session: Option<&mut ClientSession>,
36 ) -> Result<Option<T>> {
37 let op = Op::<T>::with_modification(self.clone_with_type(), filter, modification, options)?;
38 self.client().execute_operation(op, session).await
39 }
40
41 #[deeplink]
50 #[options_doc(find_one_and_delete)]
51 pub fn find_one_and_delete(&self, filter: Document) -> FindOneAndDelete<'_, T> {
52 FindOneAndDelete {
53 coll: self,
54 filter,
55 options: None,
56 session: None,
57 }
58 }
59
60 #[deeplink]
71 #[options_doc(find_one_and_update)]
72 pub fn find_one_and_update(
73 &self,
74 filter: Document,
75 update: impl Into<UpdateModifications>,
76 ) -> FindOneAndUpdate<'_, T> {
77 FindOneAndUpdate {
78 coll: self,
79 filter,
80 update: update.into(),
81 options: None,
82 session: None,
83 }
84 }
85}
86
87impl<T: Serialize + DeserializeOwned + Send + Sync> Collection<T> {
88 #[deeplink]
98 #[options_doc(find_one_and_replace)]
99 pub fn find_one_and_replace(
100 &self,
101 filter: Document,
102 replacement: impl Borrow<T>,
103 ) -> FindOneAndReplace<'_, T> {
104 FindOneAndReplace {
105 coll: self,
106 filter,
107 replacement: crate::bson_compat::serialize_to_raw_document_buf(replacement.borrow())
108 .map_err(Into::into),
109 options: None,
110 session: None,
111 }
112 }
113}
114
115#[cfg(feature = "sync")]
116impl<T: DeserializeOwned + Send + Sync> crate::sync::Collection<T> {
117 #[deeplink]
126 #[options_doc(find_one_and_delete, "run")]
127 pub fn find_one_and_delete(&self, filter: Document) -> FindOneAndDelete<'_, T> {
128 self.async_collection.find_one_and_delete(filter)
129 }
130
131 #[deeplink]
142 #[options_doc(find_one_and_update, "run")]
143 pub fn find_one_and_update(
144 &self,
145 filter: Document,
146 update: impl Into<UpdateModifications>,
147 ) -> FindOneAndUpdate<'_, T> {
148 self.async_collection.find_one_and_update(filter, update)
149 }
150}
151
152#[cfg(feature = "sync")]
153impl<T: Serialize + DeserializeOwned + Send + Sync> crate::sync::Collection<T> {
154 #[deeplink]
164 #[options_doc(find_one_and_replace, "run")]
165 pub fn find_one_and_replace(
166 &self,
167 filter: Document,
168 replacement: impl Borrow<T>,
169 ) -> FindOneAndReplace<'_, T> {
170 self.async_collection
171 .find_one_and_replace(filter, replacement)
172 }
173}
174
175#[must_use]
178pub struct FindOneAndDelete<'a, T: Send + Sync> {
179 coll: &'a Collection<T>,
180 filter: Document,
181 options: Option<FindOneAndDeleteOptions>,
182 session: Option<&'a mut ClientSession>,
183}
184
185#[option_setters(crate::coll::options::FindOneAndDeleteOptions)]
186#[export_doc(find_one_and_delete)]
187impl<'a, T: Send + Sync> FindOneAndDelete<'a, T> {
188 pub fn session(mut self, value: impl Into<&'a mut ClientSession>) -> Self {
190 self.session = Some(value.into());
191 self
192 }
193}
194
195#[action_impl]
196impl<'a, T: DeserializeOwned + Send + Sync> Action for FindOneAndDelete<'a, T> {
197 type Future = FindOneAndDeleteFuture;
198
199 async fn execute(self) -> Result<Option<T>> {
200 self.coll
201 .find_and_modify(
202 self.filter,
203 Modification::Delete,
204 self.options.map(FindAndModifyOptions::from),
205 self.session,
206 )
207 .await
208 }
209}
210
211#[must_use]
214pub struct FindOneAndUpdate<'a, T: Send + Sync> {
215 coll: &'a Collection<T>,
216 filter: Document,
217 update: UpdateModifications,
218 options: Option<FindOneAndUpdateOptions>,
219 session: Option<&'a mut ClientSession>,
220}
221
222#[option_setters(crate::coll::options::FindOneAndUpdateOptions)]
223#[export_doc(find_one_and_update)]
224impl<'a, T: Send + Sync> FindOneAndUpdate<'a, T> {
225 pub fn session(mut self, value: impl Into<&'a mut ClientSession>) -> Self {
227 self.session = Some(value.into());
228 self
229 }
230}
231
232#[action_impl]
233impl<'a, T: DeserializeOwned + Send + Sync> Action for FindOneAndUpdate<'a, T> {
234 type Future = FindOneAndUpdateFuture;
235
236 async fn execute(self) -> Result<Option<T>> {
237 self.coll
238 .find_and_modify(
239 self.filter,
240 Modification::Update(self.update.into()),
241 self.options.map(FindAndModifyOptions::from),
242 self.session,
243 )
244 .await
245 }
246}
247
248#[must_use]
251pub struct FindOneAndReplace<'a, T: Send + Sync> {
252 coll: &'a Collection<T>,
253 filter: Document,
254 replacement: Result<RawDocumentBuf>,
255 options: Option<FindOneAndReplaceOptions>,
256 session: Option<&'a mut ClientSession>,
257}
258
259#[option_setters(crate::coll::options::FindOneAndReplaceOptions)]
260#[export_doc(find_one_and_replace)]
261impl<'a, T: Send + Sync> FindOneAndReplace<'a, T> {
262 pub fn session(mut self, value: impl Into<&'a mut ClientSession>) -> Self {
264 self.session = Some(value.into());
265 self
266 }
267}
268
269#[action_impl]
270impl<'a, T: DeserializeOwned + Send + Sync> Action for FindOneAndReplace<'a, T> {
271 type Future = FindOneAndReplaceFuture;
272
273 async fn execute(self) -> Result<Option<T>> {
274 self.coll
275 .find_and_modify(
276 self.filter,
277 Modification::Update(UpdateOrReplace::Replacement(self.replacement?)),
278 self.options.map(FindAndModifyOptions::from),
279 self.session,
280 )
281 .await
282 }
283}