mongo_indexed/
lib.rs

1use mongodb::{
2  options::IndexOptions, results::CreateIndexResult, Collection, Database, IndexModel,
3};
4use serde::{de::DeserializeOwned, Serialize};
5
6pub use mongo_indexed_derive as derive;
7pub use mongodb::bson::{doc, Document};
8
9mod error;
10
11pub use error::Error;
12
13pub trait Indexed: Serialize + DeserializeOwned + Send + Sync {
14  fn default_collection_name() -> &'static str;
15  fn indexes() -> &'static [&'static str];
16  fn unique_indexes() -> &'static [&'static str];
17  fn sparse_indexes() -> &'static [&'static str];
18  fn sparse_unique_indexes() -> &'static [&'static str];
19  fn doc_indexes() -> Vec<Document>;
20  fn unique_doc_indexes() -> Vec<Document>;
21  fn sparse_doc_indexes() -> Vec<Document>;
22  fn sparse_unique_doc_indexes() -> Vec<Document>;
23}
24
25pub async fn collection<T: Indexed>(
26  db: &Database,
27  should_create_index: bool,
28) -> Result<Collection<T>, Error> {
29  collection_with_name::<T>(db, T::default_collection_name(), should_create_index).await
30}
31
32pub async fn collection_with_name<T: Indexed>(
33  db: &Database,
34  coll_name: &str,
35  should_create_index: bool,
36) -> Result<Collection<T>, Error> {
37  let coll = db.collection(coll_name);
38
39  if should_create_index {
40    for index in T::indexes() {
41      create_index(&coll, index)
42        .await
43        .map_err(|err| Error::IndexFailed { index, err })?;
44    }
45    for index in T::unique_indexes() {
46      create_unique_index(&coll, index)
47        .await
48        .map_err(|err| Error::UniqueIndexFailed { index, err })?;
49    }
50    for index in T::sparse_indexes() {
51      create_sparse_index(&coll, index)
52        .await
53        .map_err(|err| Error::SparseIndexFailed { index, err })?;
54    }
55    for index in T::sparse_unique_indexes() {
56      create_sparse_unique_index(&coll, index)
57        .await
58        .map_err(|err| Error::SparseIndexFailed { index, err })?;
59    }
60    for doc in T::doc_indexes() {
61      create_index_from_doc(&coll, doc)
62        .await
63        .map_err(|err| Error::DocIndexFailed { err })?;
64    }
65    for doc in T::unique_doc_indexes() {
66      create_unique_index_from_doc(&coll, doc)
67        .await
68        .map_err(|err| Error::UniqueDocIndexFailed { err })?;
69    }
70    for doc in T::sparse_doc_indexes() {
71      create_sparse_index_from_doc(&coll, doc)
72        .await
73        .map_err(|err| Error::SparseDocIndexFailed { err })?;
74    }
75    for doc in T::sparse_unique_doc_indexes() {
76      create_sparse_unique_index_from_doc(&coll, doc)
77        .await
78        .map_err(|err| Error::SparseDocIndexFailed { err })?;
79    }
80  }
81  Ok(coll)
82}
83
84pub async fn create_index<T: Send + Sync>(
85  collection: &Collection<T>,
86  field: &str,
87) -> mongodb::error::Result<CreateIndexResult> {
88  let index = IndexModel::builder().keys(doc! { field: 1 }).build();
89  collection.create_index(index).await
90}
91
92pub async fn create_unique_index<T: Send + Sync>(
93  collection: &Collection<T>,
94  field: &str,
95) -> mongodb::error::Result<CreateIndexResult> {
96  let options = IndexOptions::builder().unique(true).build();
97  let index = IndexModel::builder()
98    .keys(doc! { field: 1 })
99    .options(options)
100    .build();
101  collection.create_index(index).await
102}
103
104pub async fn create_sparse_index<T: Send + Sync>(
105  collection: &Collection<T>,
106  field: &str,
107) -> mongodb::error::Result<CreateIndexResult> {
108  let options = IndexOptions::builder().sparse(true).build();
109  let index = IndexModel::builder()
110    .keys(doc! { field: 1 })
111    .options(options)
112    .build();
113  collection.create_index(index).await
114}
115pub async fn create_sparse_unique_index<T: Send + Sync>(
116  collection: &Collection<T>,
117  field: &str,
118) -> mongodb::error::Result<CreateIndexResult> {
119  let options = IndexOptions::builder().sparse(true).unique(true).build();
120  let index = IndexModel::builder()
121    .keys(doc! { field: 1 })
122    .options(options)
123    .build();
124  collection.create_index(index).await
125}
126
127pub async fn create_index_from_doc<T: Send + Sync>(
128  collection: &Collection<T>,
129  index_doc: Document,
130) -> mongodb::error::Result<CreateIndexResult> {
131  let index = IndexModel::builder().keys(index_doc).build();
132  collection.create_index(index).await
133}
134
135pub async fn create_unique_index_from_doc<T: Send + Sync>(
136  collection: &Collection<T>,
137  index_doc: Document,
138) -> mongodb::error::Result<CreateIndexResult> {
139  let options = IndexOptions::builder().unique(true).build();
140  let index = IndexModel::builder()
141    .keys(index_doc)
142    .options(options)
143    .build();
144  collection.create_index(index).await
145}
146
147pub async fn create_sparse_index_from_doc<T: Send + Sync>(
148  collection: &Collection<T>,
149  index_doc: Document,
150) -> mongodb::error::Result<CreateIndexResult> {
151  let options = IndexOptions::builder().sparse(true).build();
152  let index = IndexModel::builder()
153    .keys(index_doc)
154    .options(options)
155    .build();
156  collection.create_index(index).await
157}
158
159pub async fn create_sparse_unique_index_from_doc<T: Send + Sync>(
160  collection: &Collection<T>,
161  index_doc: Document,
162) -> mongodb::error::Result<CreateIndexResult> {
163  let options = IndexOptions::builder().sparse(true).unique(true).build();
164  let index = IndexModel::builder()
165    .keys(index_doc)
166    .options(options)
167    .build();
168  collection.create_index(index).await
169}