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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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#[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#[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#[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#[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 pub fn name(mut self, name: impl Into<String>) -> Self {
273 self.name = Some(name.into());
274 self
275 }
276
277 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}