use crate::error::Error;
use mongodb::{bson::Document, options::*, ClientSession, Collection, Cursor, SessionCursor};
use serde::{Deserialize, Serialize};
pub async fn find_one<D>(
collection: &Collection<D>,
filter: Document,
options: Option<FindOneOptions>,
session: Option<&mut ClientSession>,
) -> Result<Option<D>, Error>
where
D: Serialize + for<'a> Deserialize<'a> + Send + Sync + Unpin,
{
let document = if let Some(session) = session {
collection
.find_one(filter)
.with_options(options)
.session(session)
.await
} else {
collection.find_one(filter).with_options(options).await
}
.map_err(Error::Mongo)?;
Ok(document)
}
pub struct FindManyCursor<D>
where
D: Serialize + for<'a> Deserialize<'a> + Send + Sync,
{
cursor: Option<Cursor<D>>,
session_cursor: Option<SessionCursor<D>>,
}
impl<D> FindManyCursor<D>
where
D: Serialize + for<'a> Deserialize<'a> + Send + Sync,
{
pub async fn from(
collection: &Collection<D>,
filter: Document,
options: Option<FindOptions>,
session: Option<&mut ClientSession>,
) -> Result<Self, Error> {
let (cursor, session_cursor) = if let Some(session) = session {
(
None,
Some(
collection
.find(filter)
.with_options(options)
.session(session)
.await
.map_err(Error::Mongo)?,
),
)
} else {
(
Some(
collection
.find(filter)
.with_options(options)
.await
.map_err(Error::Mongo)?,
),
None,
)
};
Ok(Self {
cursor,
session_cursor,
})
}
#[cfg(feature = "grid_fs")]
pub fn from_cursor(cursor: Cursor<D>) -> Self {
Self {
cursor: Some(cursor),
session_cursor: None,
}
}
pub async fn next(&mut self) -> Result<Option<D>, Error> {
if let Some(cursor) = &mut self.cursor {
if cursor.advance().await.map_err(Error::Mongo)? {
return Ok(Some(cursor.deserialize_current().map_err(Error::Mongo)?));
} else {
return Ok(None);
}
}
Err(Error::internal(
"Cannot call `next` on `FindManyCursor`\
when using a `ClientSession`. Please use `next_with_session`",
))
}
pub async fn next_with_session(
&mut self,
session: &mut ClientSession,
) -> Result<Option<D>, Error> {
if let Some(session_cursor) = &mut self.session_cursor {
if session_cursor
.advance(session)
.await
.map_err(Error::Mongo)?
{
return Ok(Some(
session_cursor.deserialize_current().map_err(Error::Mongo)?,
));
} else {
return Ok(None);
}
}
Err(Error::internal(
"Cannot call `next_with_session` on `FindManyCursor`\
without using a `ClientSession`. Please use `next`",
))
}
pub async fn all(mut self) -> Result<Vec<D>, Error> {
if self.cursor.is_none() {
return Err(Error::internal(
"Cannot call `all` on `FindManyCursor`\
when using a `ClientSession`. Please use `all_with_session`",
));
}
let mut documents = vec![];
while let Some(document) = self.next().await? {
documents.push(document);
}
Ok(documents)
}
pub async fn all_with_session(mut self, session: &mut ClientSession) -> Result<Vec<D>, Error> {
if self.session_cursor.is_none() {
return Err(Error::internal(
"Cannot call `all_with_session` on `FindManyCursor`\
without using a `ClientSession`. Please use `all`",
));
}
let mut documents = vec![];
while let Some(document) = self.next_with_session(session).await? {
documents.push(document);
}
Ok(documents)
}
}