use std::marker::PhantomData;
use std::time::Duration;
use mongodb::bson::Document;
use mongodb::options::{Collation, CursorType, FindOptions, Hint, ReadConcern, SelectionCriteria};
use crate::collection::Collection;
use crate::field::{AsField, Field};
use crate::filter::{AsFilter, Filter};
use crate::r#async::{Client, TypedCursor};
use crate::sort::Sort;
#[derive(Clone)]
pub struct Find<C: Collection> {
filter: Option<Document>,
options: FindOptions,
query_type: PhantomData<C>,
}
impl<C: Collection> Default for Find<C> {
fn default() -> Self {
Self::new()
}
}
impl<C: Collection> Find<C> {
pub fn new() -> Self {
Self {
filter: None,
options: FindOptions::default(),
query_type: PhantomData,
}
}
pub fn allow_disk_use(mut self, enable: bool) -> Self {
self.options.allow_partial_results = Some(enable);
self
}
pub fn allow_partial_results(mut self, enable: bool) -> Self {
self.options.allow_partial_results = Some(enable);
self
}
pub fn batch_size(mut self, size: u32) -> Self {
self.options.batch_size = Some(size);
self
}
pub fn collation(mut self, value: Collation) -> Self {
self.options.collation = Some(value);
self
}
pub fn comment(mut self, value: String) -> Self {
self.options.comment = Some(value);
self
}
pub fn cursor_type(mut self, r#type: CursorType) -> Self {
self.options.cursor_type = Some(r#type);
self
}
pub fn filter<F>(mut self, filter: F) -> crate::Result<Self>
where
C: AsFilter<F>,
F: Filter,
{
self.filter = Some(filter.into_document()?);
Ok(self)
}
pub fn hint(mut self, value: Hint) -> Self {
self.options.hint = Some(value);
self
}
pub fn limit(mut self, value: i64) -> Self {
self.options.limit = Some(value);
self
}
pub fn max(mut self, document: Document) -> Self {
self.options.max = Some(document);
self
}
pub fn max_await_time(mut self, duration: Duration) -> Self {
self.options.max_await_time = Some(duration);
self
}
pub fn max_scan(mut self, value: u64) -> Self {
self.options.max_scan = Some(value);
self
}
pub fn max_time(mut self, duration: Duration) -> Self {
self.options.max_time = Some(duration);
self
}
pub fn min(mut self, document: Document) -> Self {
self.options.min = Some(document);
self
}
pub fn no_cursor_timeout(mut self, enable: bool) -> Self {
self.options.no_cursor_timeout = Some(enable);
self
}
pub fn projection(mut self, document: Document) -> Self {
self.options.projection = Some(document);
self
}
pub fn read_concern(mut self, concern: ReadConcern) -> Self {
self.options.read_concern = Some(concern);
self
}
pub fn return_key(mut self, enable: bool) -> Self {
self.options.return_key = Some(enable);
self
}
pub fn selection_criteria(mut self, criteria: SelectionCriteria) -> Self {
self.options.selection_criteria = Some(criteria);
self
}
pub fn show_record_id(mut self, enable: bool) -> Self {
self.options.show_record_id = Some(enable);
self
}
pub fn skip(mut self, value: u64) -> Self {
self.options.skip = Some(value);
self
}
pub fn sort<F>(mut self, sort: Sort<F>) -> Self
where
C: AsField<F>,
F: Field + Into<String>,
{
self.options.sort = Some(sort.into_document());
self
}
pub async fn query(self, client: &Client) -> crate::Result<TypedCursor<C>> {
client
.database()
.collection::<Document>(C::COLLECTION)
.find(self.filter, self.options)
.await
.map(TypedCursor::from)
.map_err(crate::error::mongodb)
}
#[cfg(feature = "blocking")]
pub fn blocking(
self,
client: &crate::blocking::Client,
) -> crate::Result<crate::blocking::TypedCursor<C>> {
let resp = client.execute(crate::blocking::Request::Find(
C::COLLECTION,
self.filter,
self.options,
))?;
if let crate::blocking::Response::Find(r) = resp {
return Ok(crate::blocking::TypedCursor::from(r));
}
Err(crate::error::runtime(
"incorrect response from blocking client",
))
}
}