# mongod mongod is a rust crate for a model based database on top of MongoDB. ## Usage `mongod` allows you to use structs as `models` with data. it is build upon a MongoDB database. You need to pass a Connection URI for the database to use via the `$DB_URI` environment variable. The database to use can be configured via `$DB` environment variable. ### Models You can derive the `Model` and `Referencable` traits for your struct. This will provide you with functions like `insert()`, `delete()`, `update()`, `get()`, etc for your struct. Additionally you have to manually implement the `Validate` trait which ensures a consistent valid state of your struct in order to never insert invalid data into the database. ```rust use serde::{Deserialize, Serialize}; use mongod::Validate; use mongod::Reference; use mongod::derive::{Model, Referencable}; #[derive(Debug, Clone, Serialize, Deserialize, Model, Referencable)] struct MyStruct { _id: String, name: String, other: Option, } impl Validate for MyStruct { async fn validate(&self) -> Result<(), String> { Ok(()) } } ``` This allows you to use your struct like this: ```rust let a = MyStruct{ _id: "someid".to_string(), name: "hello".to_string(), other: None }; a.insert().await; a.update(serde_json::json!({"name": "bye"})).await.unwrap(); let new_a = MyStruct::get("someid"); ``` ### Historic data If you want certain fields to remember a history of changes you can use the `Historic` type. This type will retain previous changes along with a timestamp when updates happen. ### References A Models field can be a reference to another model using the `Reference` type. ```rust let m = MyStruct::get("someid").await.unwrap(); // get a reference from model // `reference()` is a convenience function and is exactly the same as the two references below let myref = m.reference(); let sec_ref = Reference::new(MyStruct::collection_name(), "someid").await.unwrap(); let third_ref = Reference::new("my_struct", "someid").await.unwrap(); struct OtherStruct { link: Reference } // store a reference let other = OtherStruct{ link: myref } let m: MyStruct = other.link.get().await; // get back a model from reference ``` With the `assert_reference_of!()` macro you can limit the models your reference can represent at validation. You can specify as many models as you want, but the reference must match one of them. ```rust #[derive(Debug, Clone, Serialize, Deserialize, Module, Referencable)] struct OtherStruct { /* *** */ } #[derive(Debug, Clone, Serialize, Deserialize, Module, Referencable)] struct YetAnotherStruct { /* *** */ } impl Validate for MyStruct { async fn validate(&self) -> Result<(), String> { if let Some(other) = self.other { assert_reference_of!(other, OtherStruct, YetAnotherStruct); } Ok(()) } } ``` ### Partials Sometimes you need only some fields of your `Model`. When deriving the `Model` trait you automatically get a `Partial` of your model. Partials are only meant for reading values so you cant call functions like `update()`, but you can still get a `Reference` to the original `Model`. This saves bandwidth and memory. You can access it like this: ```rust // say you are only interested in the reference field `other` of `MyStruct` let ms = MyStruct::get_partial("someid", &serde_json::json!({"other": 1})).await.unwrap(); let myref = ms.other.unwrap(); // will be there let name = ms.name.unwrap() // will panic! ``` ### Updating values You can either update the values by passing a JSON object overwriting the current values or update the values using a builder pattern. ```rust [...] struct MyStruct { _id: String, name: String, age: u32, other: Option, } let mut a = MyStruct::get("someid").await.unwrap(); // JSON a.update(serde_json::json!({"name": "bye"})).await.unwrap(); // Builder let mut changes = a.change(); // Set fields changes = changes.name("bye"); // There are type specific functions // Increment age by 1 changes = changes.age_increment(1); // Finalize let changed_model: MyStruct = changes.update().await.unwrap(); ```