This purpose of this guide is to give clear examples of inserting and fetching Rust data structures using a MongoDB database.
Vocab
Serde - Rust Library for Serializing and Deserializing data structures. Serializing - Translating data structures into a format suitable for network transfer or conversion. Deserializing - Constructing a data structure from a serialized format. BSON - Binary JSON, serialization format used by MongoDB to represent data structures. Document - Represents a single data structure.
Cargo.toml
Include the following crates in your cargo.toml file:
1 2 3 4 5
[dependencies] serde = "1.0" # serialization library serde_derive = "1.0" # automatically derives Serialize and Deserialize impls for your data bson = "0.9.0" # BSON library - makes use of Serde to Serialize and Deserialize with BSON mongodb = "0.3.2" # Official prototype MongoDB rust driver
Import the crates into your main.rs or lib.rs
1 2 3 4 5
#[macro use(bson, doc)] extern crate bson; extern crate mongodb; extern crate serde; #[macro use] extern crate serde_derive; // #[macro use] extends the macros in the crate to our modules
Preparing your data
Serde_derive is capable of implementing Serialize and Deserialize for most simple data structures. Advanced Serde topics can be found here: Serde Docs
Use #[derive(Serialize, Deserialize)] to automatically implement Serialize and Deserialize for your data.
In this example we assume MongoDB is installed on the local machine and contains a database called “Test”. We will be using a collection “People” to store our Person data structures MongoDB rust driver docs are here: MongoDB driver Docs
// only Serialize is needed here #[derive(Serialize, Deserialize,)] pubstructPerson { pub first: String, pub last: String, pub age: u16 }
implPerson {
// takes a borrowed model and returns a simple true/false result pubfninsert(&self, model: &T) ->Result<bool,bool> { match bson::to_bson(model) { Ok(model_bson) => { match model_bson{ bson::Bson::Document(model_doc) => { matchself.coll.insert_one( model_doc, None) { Ok(db_result) => { returnOk(true) }, Err(err) => { println!("Failed to insert new model doc into database:\n{}",err); returnErr(false) } } }, _ => { println!("Failed to create document from new model bson"); returnErr(false) } } }, Err(err) => { println!("Failed to create bson from new model:\n{}",err); returnErr(false) } } }
// only Deserialize is needed here #[derive(Serialize, Deserialize,)] pubstructPerson { pub first: String, pub last: String, pub age: u16 }
implPerson {
// takes a borrowed partial model and returns the model if it matches or None if it doesn't // returns a bool instead of error types pubfnfind_one(&self, model: &T) ->Result<Option<T>, bool> { match bson::to_bson(model) { Ok(model_bson) => { match model_bson{ bson::Bson::Document(model_doc) => { matchself.coll.find_one( Some(model_doc), None) { Ok(db_result) => { match db_result { Some(result_doc) => { match bson::from_bson(bson::Bson::Document(result_doc)) { Ok(result_model) => { returnOk(Some(result_model)) }, Err(err) => { println!("failed to get model from bson"); returnErr(false) } } }, None => { println!("No model found"); returnOk(None) } } }, Err(err) => { println!("Failed to delete doc from database:\n{}",err); returnErr(false) } } }, _ => { println!("Failed to create document from new model bson"); returnErr(false) } } }, Err(err) => { println!("Failed to create bson from model:\n{}",err); returnErr(false) } } }