mod gen;
pub use gen::*;
use std::marker::PhantomData;
use crate::bson::{doc, Bson, DateTime, Document};
use mongodb_internal_macros::{export_doc, options_doc};
pub struct SearchOperator<T> {
pub(crate) name: &'static str,
pub(crate) spec: Document,
_t: PhantomData<T>,
}
impl<T> SearchOperator<T> {
fn new(name: &'static str, spec: Document) -> Self {
Self {
name,
spec,
_t: PhantomData,
}
}
pub fn into_stage(self) -> Document {
search(self).into_stage()
}
pub fn into_stage_meta(self) -> Document {
search_meta(self).into_stage()
}
pub fn unit(self) -> SearchOperator<()> {
SearchOperator {
name: self.name,
spec: self.spec,
_t: PhantomData,
}
}
}
#[options_doc(atlas_search, "into_stage")]
pub fn search<T>(op: SearchOperator<T>) -> AtlasSearch {
AtlasSearch {
stage: doc! { op.name: op.spec },
}
}
pub struct AtlasSearch {
stage: Document,
}
#[export_doc(atlas_search)]
impl AtlasSearch {
pub fn concurrent(mut self, value: bool) -> Self {
self.stage.insert("concurrent", value);
self
}
pub fn count(mut self, value: Document) -> Self {
self.stage.insert("count", value);
self
}
pub fn highlight(mut self, value: Document) -> Self {
self.stage.insert("highlight", value);
self
}
pub fn index(mut self, value: impl Into<String>) -> Self {
self.stage.insert("index", value.into());
self
}
pub fn return_stored_source(mut self, value: bool) -> Self {
self.stage.insert("returnStoredSource", value);
self
}
pub fn search_after(mut self, value: impl Into<String>) -> Self {
self.stage.insert("searchAfter", value.into());
self
}
pub fn search_before(mut self, value: impl Into<String>) -> Self {
self.stage.insert("searchBefore", value.into());
self
}
pub fn score_details(mut self, value: bool) -> Self {
self.stage.insert("scoreDetails", value);
self
}
pub fn sort(mut self, value: Document) -> Self {
self.stage.insert("sort", value);
self
}
pub fn into_stage(self) -> Document {
doc! { "$search": self.stage }
}
}
#[options_doc(atlas_search_meta, "into_stage")]
pub fn search_meta<T>(op: SearchOperator<T>) -> AtlasSearchMeta {
AtlasSearchMeta {
stage: doc! { op.name: op.spec },
}
}
pub struct AtlasSearchMeta {
stage: Document,
}
#[export_doc(atlas_search_meta)]
impl AtlasSearchMeta {
pub fn count(mut self, value: Document) -> Self {
self.stage.insert("count", value);
self
}
pub fn index(mut self, value: impl Into<String>) -> Self {
self.stage.insert("index", value.into());
self
}
pub fn into_stage(self) -> Document {
doc! { "$searchMeta": self.stage }
}
}
impl<T> IntoIterator for SearchOperator<T> {
type Item = SearchOperator<T>;
type IntoIter = std::iter::Once<SearchOperator<T>>;
fn into_iter(self) -> Self::IntoIter {
std::iter::once(self)
}
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum TokenOrder {
Any,
Sequential,
Other(String),
}
impl TokenOrder {
fn name(&self) -> &str {
match self {
Self::Any => "any",
Self::Sequential => "sequential",
Self::Other(s) => s.as_str(),
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum MatchCriteria {
Any,
All,
Other(String),
}
impl MatchCriteria {
fn name(&self) -> &str {
match self {
Self::Any => "any",
Self::All => "all",
Self::Other(s) => s.as_str(),
}
}
}
mod private {
use crate::bson::{doc, Bson};
pub trait Parameter {
fn to_bson(self) -> Bson;
}
impl<T: Into<Bson>> Parameter for T {
fn to_bson(self) -> Bson {
self.into()
}
}
impl<T> Parameter for super::SearchOperator<T> {
fn to_bson(self) -> Bson {
Bson::Document(doc! { self.name: self.spec })
}
}
}
pub trait StringOrArray: private::Parameter {}
impl StringOrArray for &str {}
impl StringOrArray for String {}
#[cfg(feature = "bson-3")]
impl<const N: usize> StringOrArray for [&str; N] {}
impl StringOrArray for &[&str] {}
impl StringOrArray for &[String] {}
pub trait SearchOperatorParam: private::Parameter {}
impl<T> SearchOperatorParam for SearchOperator<T> {}
impl SearchOperatorParam for Document {}
pub mod facet {
use crate::bson::{doc, Bson, Document};
use std::marker::PhantomData;
pub struct Facet<T> {
inner: Document,
_t: PhantomData<T>,
}
impl<T> From<Facet<T>> for Bson {
fn from(value: Facet<T>) -> Self {
Bson::Document(value.inner)
}
}
pub struct String;
pub fn string(path: impl AsRef<str>) -> Facet<String> {
Facet {
inner: doc! {
"type": "string",
"path": path.as_ref(),
},
_t: PhantomData,
}
}
impl Facet<String> {
pub fn num_buckets(mut self, num: i32) -> Self {
self.inner.insert("numBuckets", num);
self
}
}
pub struct Number;
pub fn number(
path: impl AsRef<str>,
boundaries: impl IntoIterator<Item = impl Into<Bson>>,
) -> Facet<Number> {
Facet {
inner: doc! {
"type": "number",
"path": path.as_ref(),
"boundaries": boundaries.into_iter().map(Into::into).collect::<Vec<_>>(),
},
_t: PhantomData,
}
}
impl Facet<Number> {
pub fn default_bucket(mut self, bucket: impl AsRef<str>) -> Self {
self.inner.insert("default", bucket.as_ref());
self
}
}
pub struct Date;
pub fn date(
path: impl AsRef<str>,
boundaries: impl IntoIterator<Item = crate::bson::DateTime>,
) -> Facet<Date> {
Facet {
inner: doc! {
"type": "date",
"path": path.as_ref(),
"boundaries": boundaries.into_iter().collect::<Vec<_>>(),
},
_t: PhantomData,
}
}
impl Facet<Date> {
pub fn default_bucket(mut self, bucket: impl AsRef<str>) -> Self {
self.inner.insert("default", bucket.as_ref());
self
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum Relation {
Contains,
Disjoint,
Intersects,
Within,
Other(String),
}
impl Relation {
fn name(&self) -> &str {
match self {
Self::Contains => "contains",
Self::Disjoint => "disjoint",
Self::Intersects => "intersects",
Self::Within => "within",
Self::Other(s) => s,
}
}
}
pub trait DocumentOrArray: private::Parameter {}
impl DocumentOrArray for Document {}
#[cfg(feature = "bson-3")]
impl<const N: usize> DocumentOrArray for [Document; N] {}
impl DocumentOrArray for &[Document] {}
macro_rules! numeric {
($trait:ty) => {
impl $trait for i32 {}
impl $trait for i64 {}
impl $trait for u32 {}
impl $trait for f32 {}
impl $trait for f64 {}
};
}
pub trait NearOrigin: private::Parameter {}
impl NearOrigin for DateTime {}
impl NearOrigin for Document {}
numeric! { NearOrigin }
pub trait BsonNumber: private::Parameter {}
numeric! { BsonNumber }
pub trait RangeValue: private::Parameter {}
numeric! { RangeValue }
impl RangeValue for DateTime {}
impl RangeValue for &str {}
impl RangeValue for &String {}
impl RangeValue for String {}
impl RangeValue for crate::bson::oid::ObjectId {}