axum-mongodb 1.0.1

macro for axum with mongodb
Documentation
## axum-mongodb

本库旨在为Axum项目提供一种更为简洁且优雅的MongoDB集成方案,其设计灵感来源于知名框架[Nest.js](https://nestjs.com/)。通过使用本库,开发者能够在Axum项目中实现对MongoDB数据库的高度简化及高效利用。

### 使用方式

#### 1.安装依赖

```bash
cargo add axum-mongodb
```

#### 2.在入口函数使用main属性宏

**lib.rs**

```rust
use anyhow::Result;
use axum::{response::IntoResponse, routing::get, Router};
use axum_mongodb::preload::*;
use mongodb::{options::ClientOptions, Client};
use tokio::net::TcpListener;
pub mod error;
mod todos;
use todos::Todo;

use crate::todos::todos_router;

// 在lib中使用,这样生成的结构体才能在整个项目中使用
#[axum_mongodb::main]
pub async fn start() -> Result<()> {
    let client_options =
        ClientOptions::parse("mongodb://mongodb:password@localhost:21045/admin").await?;
    let client = Client::with_options(client_options)?;
    let db = client.database("todo");

    // 定义State(关键代码)
    let mongodb_server = MongoDbServer::<Servers>::new(db).await;

    let app = Router::new()
        .route("/", get(hello_world))
        .merge(todos_router())
        // 注册State
        .with_state(mongodb_server);

    let listener = TcpListener::bind("127.0.0.1:8080").await.unwrap();
    tracing::info!("listening on http://{}", listener.local_addr().unwrap());
    axum::serve(listener, app).await.unwrap();

    Ok(())
}

async fn hello_world() -> impl IntoResponse {
    "hello world"
}
```

**main.rs**

```rust
use anyhow::Result;
#[tokio::main]
async fn main() -> Result<()> {
    axum_example::start().await?;
    Ok(())
}
```

#### 3.在结构体上使用Column Derive宏

```rust
use crate::Server;
use anyhow::Result;
use axum_mongodb::futures::TryStreamExt;
// 导入axum-mongodb
use axum_mongodb::preload::*;
use mongodb::{
    bson::{self, doc, oid::ObjectId},
    results::{DeleteResult, InsertOneResult, UpdateResult},
};
use serde::{Deserialize, Serialize};

#[derive(Debug, Column, Deserialize, Serialize, Clone)]
pub struct Todo {
    #[serde(
        serialize_with = "bson::serde_helpers::serialize_object_id_as_hex_string",
        rename = "_id"
    )]
    id: ObjectId,
    description: String,
    completed: bool,
    create_time: chrono::DateTime<chrono::Local>,
    update_time: chrono::DateTime<chrono::Local>,
}

// 实现相应方法,在handler中可以调用到
impl Server<Todo> {
    pub async fn create_todo(&self, description: String) -> Result<InsertOneResult> {
        Ok(self
            .insert_one(
                Todo {
                    id: ObjectId::new(),
                    description,
                    completed: false,
                    create_time: chrono::Local::now(),
                    update_time: chrono::Local::now(),
                },
                None,
            )
            .await?)
    }
		// ...
}

```

#### 4.在axum handler中使用

```rust
use axum::{extract::Path, response::IntoResponse, Json};
use serde::Deserialize;

use super::Todo;
use crate::Server;

#[derive(Debug, Deserialize)]
pub struct TodoQuery {
    pub description: String,
    pub completed: Option<bool>,
}

pub async fn create_todo(
  	// 关键代码
    todo: Server<Todo>,
    Json(TodoQuery { description, .. }): Json<TodoQuery>,
) -> impl IntoResponse {
    let res = todo.create_todo(description).await.unwrap();
    Json(res)
}

// ...
```

#### 5.注册路由

```rust
mod controller;
use controller::{create_todo, delete_todo, get_todo, get_todos, update_todo};
mod server;
use axum::{
    routing::{get, post},
    Router,
};
use axum_mongodb::MongoDbServer;
pub use server::Todo;

use crate::Servers;

pub fn todos_router() -> Router<MongoDbServer<Servers>> {
    Router::new()
        .route("/todos", post(create_todo).get(get_todos))
        .route(
            "/todos/:id",
            get(get_todo).put(update_todo).delete(delete_todo),
        )
}

```



完整示例代码[axum-mongodb-example](https://github.com/yexiyue/axum-mongodb/blob/master/examples/axum/src/lib.rs),[示例api文档](https://apifox.com/apidoc/shared-6bef1065-5c3e-42a8-bf10-73e21f671fe1)