use std::marker::PhantomData;
use bson::{doc, Document};
use super::{action_impl, deeplink, option_setters, CollRef, Multiple, Single};
use crate::{
coll::options::AggregateOptions,
error::{Error, Result},
operation,
search_index::options::{
CreateSearchIndexOptions,
DropSearchIndexOptions,
ListSearchIndexOptions,
UpdateSearchIndexOptions,
},
Collection,
Cursor,
SearchIndexModel,
};
impl<T> Collection<T>
where
T: Send + Sync,
{
#[deeplink]
pub fn create_search_indexes(
&self,
models: impl IntoIterator<Item = SearchIndexModel>,
) -> CreateSearchIndex<Multiple> {
CreateSearchIndex {
coll: CollRef::new(self),
models: models.into_iter().collect(),
options: None,
_mode: PhantomData,
}
}
#[deeplink]
pub fn create_search_index(&self, model: SearchIndexModel) -> CreateSearchIndex<Single> {
CreateSearchIndex {
coll: CollRef::new(self),
models: vec![model],
options: None,
_mode: PhantomData,
}
}
pub fn update_search_index(
&self,
name: impl Into<String>,
definition: Document,
) -> UpdateSearchIndex {
UpdateSearchIndex {
coll: CollRef::new(self),
name: name.into(),
definition,
options: None,
}
}
pub fn drop_search_index(&self, name: impl Into<String>) -> DropSearchIndex {
DropSearchIndex {
coll: CollRef::new(self),
name: name.into(),
options: None,
}
}
#[deeplink]
pub fn list_search_indexes(&self) -> ListSearchIndexes {
ListSearchIndexes {
coll: CollRef::new(self),
name: None,
agg_options: None,
options: None,
}
}
}
#[cfg(feature = "sync")]
impl<T> crate::sync::Collection<T>
where
T: Send + Sync,
{
#[deeplink]
pub fn create_search_indexes(
&self,
models: impl IntoIterator<Item = SearchIndexModel>,
) -> CreateSearchIndex<Multiple> {
self.async_collection.create_search_indexes(models)
}
#[deeplink]
pub fn create_search_index(&self, model: SearchIndexModel) -> CreateSearchIndex<Single> {
self.async_collection.create_search_index(model)
}
pub fn update_search_index(
&self,
name: impl Into<String>,
definition: Document,
) -> UpdateSearchIndex {
self.async_collection.update_search_index(name, definition)
}
pub fn drop_search_index(&self, name: impl Into<String>) -> DropSearchIndex {
self.async_collection.drop_search_index(name)
}
#[deeplink]
pub fn list_search_indexes(&self) -> ListSearchIndexes {
self.async_collection.list_search_indexes()
}
}
#[must_use]
pub struct CreateSearchIndex<'a, Mode> {
coll: CollRef<'a>,
models: Vec<SearchIndexModel>,
options: Option<CreateSearchIndexOptions>,
_mode: PhantomData<Mode>,
}
impl<'a, Mode> CreateSearchIndex<'a, Mode> {
option_setters! { options: CreateSearchIndexOptions;
}
}
#[action_impl]
impl<'a> Action for CreateSearchIndex<'a, Multiple> {
type Future = CreateSearchIndexesFuture;
async fn execute(self) -> Result<Vec<String>> {
let op = operation::CreateSearchIndexes::new(self.coll.namespace(), self.models);
self.coll.client().execute_operation(op, None).await
}
}
#[action_impl]
impl<'a> Action for CreateSearchIndex<'a, Single> {
type Future = CreateSearchIndexFuture;
async fn execute(self) -> Result<String> {
let mut names = self
.coll
.create_search_indexes(self.models)
.with_options(self.options)
.await?;
match names.len() {
1 => Ok(names.pop().unwrap()),
n => Err(Error::internal(format!("expected 1 index name, got {}", n))),
}
}
}
#[must_use]
pub struct UpdateSearchIndex<'a> {
coll: CollRef<'a>,
name: String,
definition: Document,
options: Option<UpdateSearchIndexOptions>,
}
impl<'a> UpdateSearchIndex<'a> {
option_setters! { options: UpdateSearchIndexOptions; }
}
#[action_impl]
impl<'a> Action for UpdateSearchIndex<'a> {
type Future = UpdateSearchIndexFuture;
async fn execute(self) -> Result<()> {
let op =
operation::UpdateSearchIndex::new(self.coll.namespace(), self.name, self.definition);
self.coll.client().execute_operation(op, None).await
}
}
#[must_use]
pub struct DropSearchIndex<'a> {
coll: CollRef<'a>,
name: String,
options: Option<DropSearchIndexOptions>,
}
impl<'a> DropSearchIndex<'a> {
option_setters! { options: DropSearchIndexOptions; }
}
#[action_impl]
impl<'a> Action for DropSearchIndex<'a> {
type Future = DropSearchIndexFuture;
async fn execute(self) -> Result<()> {
let op = operation::DropSearchIndex::new(self.coll.namespace(), self.name);
self.coll.client().execute_operation(op, None).await
}
}
#[must_use]
pub struct ListSearchIndexes<'a> {
coll: CollRef<'a>,
name: Option<String>,
agg_options: Option<AggregateOptions>,
options: Option<ListSearchIndexOptions>,
}
impl<'a> ListSearchIndexes<'a> {
option_setters! { options: ListSearchIndexOptions; }
pub fn name(mut self, name: impl Into<String>) -> Self {
self.name = Some(name.into());
self
}
pub fn aggregate_options(mut self, value: AggregateOptions) -> Self {
self.agg_options = Some(value);
self
}
}
#[action_impl(sync = crate::sync::Cursor<Document>)]
impl<'a> Action for ListSearchIndexes<'a> {
type Future = ListSearchIndexesFuture;
async fn execute(self) -> Result<Cursor<Document>> {
let mut inner = doc! {};
if let Some(name) = self.name {
inner.insert("name", name);
}
self.coll
.clone_unconcerned()
.aggregate(vec![doc! {
"$listSearchIndexes": inner,
}])
.with_options(self.agg_options)
.await
}
}