simple_mongo/
lib.rs

1use futures::TryStreamExt;
2use mongodb::{
3    self, Client, Collection, Database,
4    bson::{self, doc},
5    options::ClientOptions,
6};
7use serde::{Deserialize, Serialize};
8
9
10pub use mongodb::bson::oid::ObjectId;
11
12mod traits;
13pub use traits::MongoObject;
14
15mod structures;
16pub use structures::{options::Options, credentials::Credentials}; 
17
18
19
20pub struct SimpleMongo<T>
21where
22    T: for<'de> Deserialize<'de> + Sync + Send + Serialize + MongoObject + Clone,
23{
24    #[allow(dead_code)]
25    options: Options,
26    collection: Collection<T>,
27    #[allow(dead_code)]
28    database: Database,
29}
30
31impl<T> SimpleMongo<T>
32where
33    T: Send + Sync + for<'de> Deserialize<'de> + Serialize + MongoObject + Clone,
34{
35    pub fn parse_id(id: &str) -> String {
36        ObjectId::parse_str(id)
37            .expect(&format!("{id} is not a valid id"))
38            .to_string()
39    }
40
41    pub fn add_credentials_to_url(url:&str,user:&str,password:&str)->String{
42
43        let mut splitted = url.split("//");
44    
45        let mongo =splitted.next().unwrap();
46    
47        let rest = splitted.next().unwrap();
48    
49         format!("{mongo}//{user}:{password}@{rest}")
50    }
51
52    pub async fn connect(options: Options) -> SimpleMongo<T> {
53
54        let mut parsed_options = options.clone();
55        if let Some(ref x) = parsed_options.credentials{
56            let new_uri = SimpleMongo::<T>::add_credentials_to_url(&parsed_options.uri, &x.username, &x.password);
57            parsed_options.uri = new_uri;
58        }
59        
60        let client =
61            Client::with_options(ClientOptions::parse(&parsed_options.uri).await.unwrap()).map_err(|e| format!("Errore  connecting to  MongoDB: {}", e)).unwrap();
62            // Test the connection by making a simple query
63        
64        let database: Database = client.database(&options.database_name);
65        let collection = database.collection::<T>(&options.collection_path);
66        collection.find(doc! {}).await.unwrap();
67        return SimpleMongo {
68            options:parsed_options,
69            database,
70            collection,
71        };
72    }
73
74    pub async fn list_all(&self) -> Vec<T> {
75        let cursor = self.collection.find(doc! {}).await.ok().unwrap();
76
77        let res: Vec<T> = cursor.try_collect().await.unwrap();
78        res
79    }
80
81    pub async fn find_one_by_id(&self, id: &str) -> Option<T> {
82        let parsed_id: String = SimpleMongo::<T>::parse_id(id);
83        self.collection
84            .find_one(doc! {"id":parsed_id})
85            .await
86            .ok()
87            .unwrap()
88    }
89
90    pub async fn insert_one(&self, item: T) -> Option<T> {
91        if let Some(_) = self.collection.insert_one(&item).await.ok() {
92            return self.find_one_by_id(&item.id()).await;
93        } else {
94            return None;
95        }
96    }
97
98    pub async fn remove_one_by_id(&self, id: &str) -> Option<T> {
99        let parsed_id: String = SimpleMongo::<T>::parse_id(id);
100        if let Some(res) = self
101            .collection
102            .find_one_and_delete(doc! {"id":parsed_id})
103            .await
104            .ok()
105        {
106            return res;
107        } else {
108            return None;
109        }
110    }
111
112    pub async fn clear(&self) -> bool {
113        self.collection.delete_many(doc! {}).await.unwrap();
114        self.collection.count_documents(doc! {}).await.unwrap() == 0
115    }
116
117    pub async fn update_one_by_id(&self, id: &str, update: T) -> Option<T> {
118        let mut new_item: T = update.clone();
119        new_item.set_id(id);
120
121        let update_doc = bson::to_document(&new_item).unwrap(); // Convertiamo T in BSON
122        let update_query = doc! { "$set": &update_doc }; // 
123
124        let parsed_id: String = SimpleMongo::<T>::parse_id(id);
125        if let Some(res) = self
126            .collection
127            .update_one(doc! {"id":parsed_id}, update_query)
128            .await
129            .ok()
130        {
131            if res.modified_count == 0 {
132                return None;
133            } else {
134                return Some(new_item);
135            }
136        } else {
137            None
138        }
139    }
140}