Skip to content

Commit 2b83a87

Browse files
authored
RUST-1872 Convert index management methods to fluent style (#1058)
1 parent 4102f4a commit 2b83a87

File tree

8 files changed

+342
-133
lines changed

8 files changed

+342
-133
lines changed

src/action.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ mod list_indexes;
2121
mod perf;
2222
mod replace_one;
2323
mod run_command;
24+
mod search_index;
2425
mod session;
2526
mod shutdown;
2627
mod update;
@@ -47,6 +48,7 @@ pub use list_indexes::ListIndexes;
4748
pub use perf::WarmConnectionPool;
4849
pub use replace_one::ReplaceOne;
4950
pub use run_command::{RunCommand, RunCursorCommand};
51+
pub use search_index::{CreateSearchIndex, DropSearchIndex, ListSearchIndexes, UpdateSearchIndex};
5052
pub use session::StartSession;
5153
pub use shutdown::Shutdown;
5254
pub use update::Update;
@@ -76,6 +78,7 @@ macro_rules! option_setters {
7678
$opt_name:ident: $opt_ty:ty,
7779
)*
7880
) => {
81+
#[allow(unused)]
7982
fn options(&mut self) -> &mut $opt_field_ty {
8083
self.$opt_field.get_or_insert_with(<$opt_field_ty>::default)
8184
}

src/action/create_collection.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ impl Database {
1212
///
1313
/// `await` will return d[`Result<()>`].
1414
#[deeplink]
15-
pub fn create_collection(&self, name: impl AsRef<str>) -> CreateCollection {
15+
pub fn create_collection(&self, name: impl Into<String>) -> CreateCollection {
1616
CreateCollection {
1717
db: self,
18-
name: name.as_ref().to_owned(),
18+
name: name.into(),
1919
options: None,
2020
session: None,
2121
}
@@ -31,7 +31,7 @@ impl crate::sync::Database {
3131
///
3232
/// [`run`](CreateCollection::run) will return d[`Result<()>`].
3333
#[deeplink]
34-
pub fn create_collection(&self, name: impl AsRef<str>) -> CreateCollection {
34+
pub fn create_collection(&self, name: impl Into<String>) -> CreateCollection {
3535
self.async_database.create_collection(name)
3636
}
3737
}

src/action/gridfs/download.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ impl GridFsBucket {
3030
#[deeplink]
3131
pub fn open_download_stream_by_name(
3232
&self,
33-
filename: impl AsRef<str>,
33+
filename: impl Into<String>,
3434
) -> OpenDownloadStreamByName {
3535
OpenDownloadStreamByName {
3636
bucket: self,
37-
filename: filename.as_ref().to_owned(),
37+
filename: filename.into(),
3838
options: None,
3939
}
4040
}
@@ -113,7 +113,7 @@ impl crate::sync::gridfs::GridFsBucket {
113113
#[deeplink]
114114
pub fn open_download_stream_by_name(
115115
&self,
116-
filename: impl AsRef<str>,
116+
filename: impl Into<String>,
117117
) -> OpenDownloadStreamByName {
118118
self.async_bucket.open_download_stream_by_name(filename)
119119
}

src/action/gridfs/rename.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ impl GridFsBucket {
77
/// error if the `id` does not match any files in the bucket.
88
///
99
/// `await` will return [`Result<()>`].
10-
pub fn rename(&self, id: Bson, new_filename: impl AsRef<str>) -> Rename {
10+
pub fn rename(&self, id: Bson, new_filename: impl Into<String>) -> Rename {
1111
Rename {
1212
bucket: self,
1313
id,
14-
new_filename: new_filename.as_ref().to_owned(),
14+
new_filename: new_filename.into(),
1515
}
1616
}
1717
}
@@ -22,7 +22,7 @@ impl crate::sync::gridfs::GridFsBucket {
2222
/// error if the `id` does not match any files in the bucket.
2323
///
2424
/// [`run`](Rename::run) will return [`Result<()>`].
25-
pub fn rename(&self, id: Bson, new_filename: impl AsRef<str>) -> Rename {
25+
pub fn rename(&self, id: Bson, new_filename: impl Into<String>) -> Rename {
2626
self.async_bucket.rename(id, new_filename)
2727
}
2828
}

src/action/search_index.rs

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

0 commit comments

Comments
 (0)