Rust MongoDB Driver

Rust MongoDB Driver

Rust の MongoDB Driver を少しやったので。
Rust よくわからないので結構詰まった。
MongoDB Driver のバージョンは、2.x です。

ソースコード

サンプルコード

use mongodb::bson::{doc};
use mongodb::options::{FindOptions,ClientOptions};
use mongodb::{Client, Collection};
use tokio;
use crate::CustomError::NotFound;
use futures::stream::StreamExt;
use serde::{Serialize,Deserialize};
use derive_more::{Display, Error};
const DB_NAME: &str = "todo_list";
const COLLECTION_NAME: &str = "todos";

#[derive(Debug, Serialize, Deserialize)]
pub struct Todo {
    // #[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
    pub name: String,
}

#[derive(Clone, Debug)]
pub struct MongoDbClient {
    client: Client,
}

impl MongoDbClient{
    pub async fn new(mongodb_uri: String) -> Self {
        println!("{}", mongodb_uri);
        let mut client_options = ClientOptions::parse(mongodb_uri).await.unwrap();
        println!("bbb");
        client_options.app_name = Some("My App".to_string());
        let client = Client::with_options(client_options).expect("failed to create client");
        for db_name in client.list_database_names(None, None).await.expect("failed to get database list") {
            println!("{}", db_name);
        }
        MongoDbClient{
            client: client,
        }
    }

    pub async fn get_all_todos(&self) -> Result<Vec<Todo>>{
        let mut result = Vec::new();
        let collection = self.get_todos_collection().await;
        let filter = doc!{};
        let find_options = FindOptions::builder().sort(doc! {"name": 1}).build();
        let mut todos = collection.find(filter, find_options).await?;
        while let Some(todo) = todos.next().await {
            result.push(todo?)
        }
        Ok(result)
    }

    pub async fn create_todo(&self, todo: Todo) -> Result<Todo>{
        let collection = self.get_todos_collection().await;
        let insert_result = collection.insert_one(todo, None).await?;
        let filter = doc!{"_id": &insert_result.inserted_id};
        collection.find_one(filter, None).await?.ok_or(NotFound {
            message: String::from("Can't find a created todo")
        })
    }

    pub async fn get_todos_collection(&self) -> Collection<Todo>{
        self.client
            .database(DB_NAME)
            .collection::<Todo>(COLLECTION_NAME)
    }

}

#[derive(Debug, Display, Error)]
pub enum CustomError {
    #[display(fmt = message)]
    MongoDbError {
        message: String,
    },
    #[display(fmt = message)]
    NotFound {
        message: String,
    },
}

impl From<mongodb::error::Error> for CustomError {
    fn from(source: mongodb::error::Error) -> Self {
        Self::MongoDbError {
            message: source.to_string(),
        }
    }
}

impl From<mongodb::bson::oid::Error> for CustomError {
    fn from(source: mongodb::bson::oid::Error) -> Self {
        Self::NotFound {
            message: source.to_string(),
        }
    }
}


#[allow(dead_code)]
type Result<T> = std::result::Result<T,CustomError>;

#[tokio::main]
async fn main(){
    // let _ = _connecting().await;
    let mongodb_uri = "mongodb://localhost:27017".to_string();
    // let _ = _connecting().await;
    let mongodb_client = MongoDbClient::new(mongodb_uri).await;
    let todo_list = match mongodb_client.get_all_todos().await{
        Ok(x) => x,
        Err(_) => Vec::new(),
    };
    eprintln!("zz {}", todo_list.len());
    for x in todo_list{
        println!("{}", x.name)
    }
    let todo = Todo{
        name: "hogeee".to_string(),
    };
    let _ = mongodb_client.create_todo(todo).await;

}

Cargo.toml

[package]
name = "mongodb"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
mongodb = "*"
tokio = "*"
serde = "*"
derive_more = "*"
futures = "*"