mongodb/action/
search_index.rs

1use std::marker::PhantomData;
2
3use crate::bson::{doc, Document};
4
5use super::{
6    action_impl,
7    deeplink,
8    export_doc,
9    option_setters,
10    options_doc,
11    CollRef,
12    Multiple,
13    Single,
14};
15use crate::{
16    coll::options::AggregateOptions,
17    error::{Error, Result},
18    operation,
19    search_index::options::{
20        CreateSearchIndexOptions,
21        DropSearchIndexOptions,
22        ListSearchIndexOptions,
23        UpdateSearchIndexOptions,
24    },
25    Collection,
26    Cursor,
27    SearchIndexModel,
28};
29
30impl<T> Collection<T>
31where
32    T: Send + Sync,
33{
34    /// Creates multiple search indexes on the collection.
35    ///
36    /// `await` will return d[`Result<Vec<String>>`].
37    #[deeplink]
38    #[options_doc(create_search_index)]
39    pub fn create_search_indexes(
40        &self,
41        models: impl IntoIterator<Item = SearchIndexModel>,
42    ) -> CreateSearchIndex<'_, Multiple> {
43        CreateSearchIndex {
44            coll: CollRef::new(self),
45            models: models.into_iter().collect(),
46            options: None,
47            _mode: PhantomData,
48        }
49    }
50
51    /// Convenience method for creating a single search index.
52    ///
53    /// `await` will return d[`Result<String>`].
54    #[deeplink]
55    #[options_doc(create_search_index)]
56    pub fn create_search_index(&self, model: SearchIndexModel) -> CreateSearchIndex<'_, Single> {
57        CreateSearchIndex {
58            coll: CollRef::new(self),
59            models: vec![model],
60            options: None,
61            _mode: PhantomData,
62        }
63    }
64
65    /// Updates the search index with the given name to use the provided definition.
66    ///
67    /// `await` will return [`Result<()>`].
68    #[options_doc(update_search_index)]
69    pub fn update_search_index(
70        &self,
71        name: impl Into<String>,
72        definition: Document,
73    ) -> UpdateSearchIndex<'_> {
74        UpdateSearchIndex {
75            coll: CollRef::new(self),
76            name: name.into(),
77            definition,
78            options: None,
79        }
80    }
81
82    /// Drops the search index with the given name.
83    ///
84    /// `await` will return [`Result<()>`].
85    #[options_doc(drop_search_index)]
86    pub fn drop_search_index(&self, name: impl Into<String>) -> DropSearchIndex<'_> {
87        DropSearchIndex {
88            coll: CollRef::new(self),
89            name: name.into(),
90            options: None,
91        }
92    }
93
94    /// Gets index information for one or more search indexes in the collection.
95    ///
96    /// If name is not specified, information for all indexes on the specified collection will be
97    /// returned.
98    ///
99    /// `await` will return d[`Result<Cursor<Document>>`].
100    #[deeplink]
101    #[options_doc(list_search_indexes)]
102    pub fn list_search_indexes(&self) -> ListSearchIndexes<'_> {
103        ListSearchIndexes {
104            coll: CollRef::new(self),
105            name: None,
106            agg_options: None,
107            options: None,
108        }
109    }
110}
111
112#[cfg(feature = "sync")]
113impl<T> crate::sync::Collection<T>
114where
115    T: Send + Sync,
116{
117    /// Creates multiple search indexes on the collection.
118    ///
119    /// [`run`](CreateSearchIndex::run) will return d[`Result<Vec<String>>`].
120    #[deeplink]
121    #[options_doc(create_search_index, "run")]
122    pub fn create_search_indexes(
123        &self,
124        models: impl IntoIterator<Item = SearchIndexModel>,
125    ) -> CreateSearchIndex<'_, Multiple> {
126        self.async_collection.create_search_indexes(models)
127    }
128
129    /// Convenience method for creating a single search index.
130    ///
131    /// [`run`](CreateSearchIndex::run) will return d[`Result<String>`].
132    #[deeplink]
133    #[options_doc(create_search_index, "run")]
134    pub fn create_search_index(&self, model: SearchIndexModel) -> CreateSearchIndex<'_, Single> {
135        self.async_collection.create_search_index(model)
136    }
137
138    /// Updates the search index with the given name to use the provided definition.
139    ///
140    /// [`run`](UpdateSearchIndex::run) will return [`Result<()>`].
141    #[options_doc(update_search_index, "run")]
142    pub fn update_search_index(
143        &self,
144        name: impl Into<String>,
145        definition: Document,
146    ) -> UpdateSearchIndex<'_> {
147        self.async_collection.update_search_index(name, definition)
148    }
149
150    /// Drops the search index with the given name.
151    ///
152    /// [`run`](DropSearchIndex::run) will return [`Result<()>`].
153    #[options_doc(drop_search_index, "run")]
154    pub fn drop_search_index(&self, name: impl Into<String>) -> DropSearchIndex<'_> {
155        self.async_collection.drop_search_index(name)
156    }
157
158    /// Gets index information for one or more search indexes in the collection.
159    ///
160    /// If name is not specified, information for all indexes on the specified collection will be
161    /// returned.
162    ///
163    /// [`run`](ListSearchIndexes::run) will return d[`Result<crate::sync::Cursor<Document>>`].
164    #[deeplink]
165    #[options_doc(list_search_indexes, "run")]
166    pub fn list_search_indexes(&self) -> ListSearchIndexes<'_> {
167        self.async_collection.list_search_indexes()
168    }
169}
170
171/// Create search indexes on a collection.  Construct with [`Collection::create_search_index`] or
172/// [`Collection::create_search_indexes`].
173#[must_use]
174pub struct CreateSearchIndex<'a, Mode> {
175    coll: CollRef<'a>,
176    models: Vec<SearchIndexModel>,
177    options: Option<CreateSearchIndexOptions>,
178    _mode: PhantomData<Mode>,
179}
180
181#[option_setters(crate::search_index::options::CreateSearchIndexOptions)]
182#[export_doc(create_search_index)]
183impl<Mode> CreateSearchIndex<'_, Mode> {}
184
185#[action_impl]
186impl<'a> Action for CreateSearchIndex<'a, Multiple> {
187    type Future = CreateSearchIndexesFuture;
188
189    async fn execute(self) -> Result<Vec<String>> {
190        let op = operation::CreateSearchIndexes::new(self.coll.namespace(), self.models);
191        self.coll.client().execute_operation(op, None).await
192    }
193}
194
195#[action_impl]
196impl<'a> Action for CreateSearchIndex<'a, Single> {
197    type Future = CreateSearchIndexFuture;
198
199    async fn execute(self) -> Result<String> {
200        let mut names = self
201            .coll
202            .create_search_indexes(self.models)
203            .with_options(self.options)
204            .await?;
205        match names.len() {
206            1 => Ok(names.pop().unwrap()),
207            n => Err(Error::internal(format!("expected 1 index name, got {n}"))),
208        }
209    }
210}
211
212/// Updates a specific search index to use a new definition.  Construct with
213/// [`Collection::update_search_index`].
214#[must_use]
215pub struct UpdateSearchIndex<'a> {
216    coll: CollRef<'a>,
217    name: String,
218    definition: Document,
219    options: Option<UpdateSearchIndexOptions>,
220}
221
222#[option_setters(crate::search_index::options::UpdateSearchIndexOptions)]
223#[export_doc(update_search_index)]
224impl UpdateSearchIndex<'_> {}
225
226#[action_impl]
227impl<'a> Action for UpdateSearchIndex<'a> {
228    type Future = UpdateSearchIndexFuture;
229
230    async fn execute(self) -> Result<()> {
231        let op =
232            operation::UpdateSearchIndex::new(self.coll.namespace(), self.name, self.definition);
233        self.coll.client().execute_operation(op, None).await
234    }
235}
236
237/// Drops a specific search index.  Construct with [`Collection::drop_search_index`].
238#[must_use]
239pub struct DropSearchIndex<'a> {
240    coll: CollRef<'a>,
241    name: String,
242    options: Option<DropSearchIndexOptions>,
243}
244
245#[option_setters(crate::search_index::options::DropSearchIndexOptions)]
246#[export_doc(drop_search_index)]
247impl DropSearchIndex<'_> {}
248
249#[action_impl]
250impl<'a> Action for DropSearchIndex<'a> {
251    type Future = DropSearchIndexFuture;
252
253    async fn execute(self) -> Result<()> {
254        let op = operation::DropSearchIndex::new(self.coll.namespace(), self.name);
255        self.coll.client().execute_operation(op, None).await
256    }
257}
258
259/// Gets index information for one or more search indexes in a collection.
260#[must_use]
261pub struct ListSearchIndexes<'a> {
262    coll: CollRef<'a>,
263    name: Option<String>,
264    agg_options: Option<AggregateOptions>,
265    options: Option<ListSearchIndexOptions>,
266}
267
268#[option_setters(crate::search_index::options::ListSearchIndexOptions)]
269#[export_doc(list_search_indexes)]
270impl ListSearchIndexes<'_> {
271    /// Get information for the named index.
272    pub fn name(mut self, name: impl Into<String>) -> Self {
273        self.name = Some(name.into());
274        self
275    }
276
277    /// Set aggregation options.
278    pub fn aggregate_options(mut self, value: AggregateOptions) -> Self {
279        self.agg_options = Some(value);
280        self
281    }
282}
283
284#[action_impl(sync = crate::sync::Cursor<Document>)]
285impl<'a> Action for ListSearchIndexes<'a> {
286    type Future = ListSearchIndexesFuture;
287
288    async fn execute(self) -> Result<Cursor<Document>> {
289        let mut inner = doc! {};
290        if let Some(name) = self.name {
291            inner.insert("name", name);
292        }
293        self.coll
294            .clone_unconcerned()
295            .aggregate(vec![doc! {
296                "$listSearchIndexes": inner,
297            }])
298            .with_options(self.agg_options)
299            .await
300    }
301}