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}