tauri_plugin_mongoose/db/
documents.rs1use crate::db::state::{get_client, get_db_name};
2use futures::stream::TryStreamExt;
3use mongodb::{
4 bson::{oid::ObjectId, Document},
5 options::{FindOneOptions as MongoFindOneOptions, FindOptions as MongoFindOptions},
6};
7use serde::Deserialize;
8use serde_json::Value;
9
10#[derive(Debug, Deserialize)]
11pub struct SearchOptions {
12 pub skip: Option<u64>,
13 pub limit: Option<i64>,
14 pub page: Option<u64>,
15 pub sort: Option<Value>,
16}
17
18pub async fn create_document(collection_name: String, document: Value) -> Result<Value, String> {
19 let client = get_client().await?;
20 let db_name = get_db_name().await;
21
22 let db = client.database(&db_name);
23 let collection = db.collection::<Document>(&collection_name);
24
25 let mut bson_doc = mongodb::bson::to_document(&document).map_err(|e| e.to_string())?;
26
27 if !bson_doc.contains_key("_id") {
28 bson_doc.insert("_id", ObjectId::new());
29 }
30
31 collection
32 .insert_one(bson_doc.clone(), None)
33 .await
34 .map_err(|e| e.to_string())?;
35
36 let json_doc: Value = mongodb::bson::from_document(bson_doc).map_err(|e| e.to_string())?;
37 Ok(json_doc)
38}
39
40pub async fn get_document_by_id(
41 collection_name: String,
42 id: String,
43) -> Result<Option<Value>, String> {
44 let client = get_client().await?;
45 let db_name = get_db_name().await;
46
47 let db = client.database(&db_name);
48 let collection = db.collection::<Document>(&collection_name);
49
50 let oid = ObjectId::parse_str(&id).map_err(|e| format!("Invalid ID format: {}", e))?;
51 let filter = mongodb::bson::doc! { "_id": oid };
52
53 let result = collection
54 .find_one(filter, None)
55 .await
56 .map_err(|e| e.to_string())?;
57
58 match result {
59 Some(doc) => {
60 let json_doc: Value = mongodb::bson::from_document(doc).map_err(|e| e.to_string())?;
61 Ok(Some(json_doc))
62 }
63 None => Ok(None),
64 }
65}
66
67pub async fn find_documents(
68 collection_name: String,
69 filter: Option<Value>,
70 options: Option<SearchOptions>,
71) -> Result<Vec<Value>, String> {
72 let client = get_client().await?;
73 let db_name = get_db_name().await;
74
75 let db = client.database(&db_name);
76 let collection = db.collection::<Document>(&collection_name);
77
78 let mut find_options = MongoFindOptions::builder().build();
79
80 if let Some(opts) = options {
81 if let Some(limit) = opts.limit {
82 find_options.limit = Some(limit);
83 }
84
85 let mut skip = opts.skip.unwrap_or(0);
86 if let Some(page) = opts.page {
87 if page > 0 {
88 let limit = opts.limit.unwrap_or(10); skip = (page as u64 - 1) * (limit as u64);
90 if find_options.limit.is_none() {
92 find_options.limit = Some(limit);
93 }
94 }
95 }
96 find_options.skip = Some(skip);
97
98 if let Some(sort) = opts.sort {
99 if let Ok(sort_doc) = mongodb::bson::to_document(&sort) {
100 find_options.sort = Some(sort_doc);
101 }
102 }
103 }
104
105 let query = if let Some(f) = filter {
106 mongodb::bson::to_document(&f).map_err(|e| e.to_string())?
107 } else {
108 mongodb::bson::doc! {}
109 };
110
111 let mut cursor = collection
112 .find(query, find_options)
113 .await
114 .map_err(|e| e.to_string())?;
115
116 let mut docs = Vec::new();
117 while let Some(result) = cursor.try_next().await.map_err(|e| e.to_string())? {
118 let json_doc: Value = mongodb::bson::from_document(result).map_err(|e| e.to_string())?;
119 docs.push(json_doc);
120 }
121
122 Ok(docs)
123}
124
125pub async fn find_one_document(
126 collection_name: String,
127 filter: Option<Value>,
128 options: Option<SearchOptions>,
129) -> Result<Option<Value>, String> {
130 let client = get_client().await?;
131 let db_name = get_db_name().await;
132
133 let db = client.database(&db_name);
134 let collection = db.collection::<Document>(&collection_name);
135
136 let mut find_options = MongoFindOneOptions::builder().build();
137
138 if let Some(opts) = options {
139 if let Some(skip) = opts.skip {
140 find_options.skip = Some(skip);
141 }
142
143 if let Some(sort) = opts.sort {
144 if let Ok(sort_doc) = mongodb::bson::to_document(&sort) {
145 find_options.sort = Some(sort_doc);
146 }
147 }
148 }
151
152 let query = if let Some(f) = filter {
153 mongodb::bson::to_document(&f).map_err(|e| e.to_string())?
154 } else {
155 mongodb::bson::doc! {}
156 };
157
158 let result = collection
159 .find_one(query, find_options)
160 .await
161 .map_err(|e| e.to_string())?;
162
163 match result {
164 Some(doc) => {
165 let json_doc: Value = mongodb::bson::from_document(doc).map_err(|e| e.to_string())?;
166 Ok(Some(json_doc))
167 }
168 None => Ok(None),
169 }
170}
171
172pub async fn update_one_document(
173 collection_name: String,
174 filter: Value,
175 update: Value,
176 options: Option<Value>,
177) -> Result<Value, String> {
178 let client = get_client().await?;
179 let db_name = get_db_name().await;
180
181 let db = client.database(&db_name);
182 let collection = db.collection::<Document>(&collection_name);
183
184 let filter_doc = mongodb::bson::to_document(&filter).map_err(|e| e.to_string())?;
185 let update_doc = mongodb::bson::to_document(&update).map_err(|e| e.to_string())?;
186
187 let mut update_options = mongodb::options::UpdateOptions::builder().build();
188
189 if let Some(opts) = options {
190 if let Some(upsert) = opts.get("upsert").and_then(|v| v.as_bool()) {
191 update_options.upsert = Some(upsert);
192 }
193 }
194
195 let result = collection
196 .update_one(filter_doc, update_doc, update_options)
197 .await
198 .map_err(|e| e.to_string())?;
199
200 let result_json = serde_json::to_value(&result).map_err(|e| e.to_string())?;
201 Ok(result_json)
202}