Rust Actix Web 是否支持 MongoDB?

Does the Rust Actix Web support MongoDB?

我有一个新的后端学习 Rust 编程。 从 Web 框架开始。 因为我想将 Rust 后端与 MongoDB 一起使用,所以我有 Nickel 的示例代码。 反正我也看到有Actix Web Framework

Actix Web 是否像 Nickel 一样支持 MongoDB?

以下示例提供镍 MongoDB。

//main.rs — Nickel
#[macro_use] 
extern crate nickel;
extern crate rustc_serialize;

#[macro_use(bson, doc)]
extern crate bson;
extern crate mongodb;

// Nickel
use nickel::{Nickel, JsonBody, HttpRouter, MediaType};
use nickel::status::StatusCode::{self};

// MongoDB
use mongodb::{Bson, bson, doc};
use mongodb::{Client, ThreadedClient};
use mongodb::db::ThreadedDatabase;
use mongodb::error::Result as MongoResult;

// bson
use bson::{Bson, Document};
use bson::oid::ObjectId;

// serde
use serde::{Serialize, Deserialize};

use std::fs::File;
use std::io::Read;
#[derive(Debug, Serialize, Deserialize)]
struct User {
    firstname: String,
    lastname: String,
    email: String
}

fn main(){
    let mut server = Nickel::new();
    let mut router = Nickel::router();

    router.get("/users", middleware! { |_req, _res|
        let client = Client::connect("localhost", 27017)
            .ok().expect("Error establishing connection.");

        let coll = client.db("rusty").collection("users");

        let mut cursor = coll.find(None, None).unwrap();
        let mut data_result = "{\"data\":[".to_owned();

        for (i, result) in cursor.enumerate() {

            if let Ok(item) = result {
                if let Some(&Bson::String(ref firstname)) = item.get("firstname") {
                    let string_data = if i == 0 {
                        format!("{},", firstname)
                    } else {
                        format!("{},", firstname)
                    };
                data_result.push_str(&string_data);
            }
        }
    }
    data_result.push_str("]}");

    format!("{}", data_result)

    });

    router.post("/users/new", middleware! { |_req, _res|
        let user = _req.json_as::<User>().unwrap();
        let firstname = user.firstname.to_string();
        let lastname = user.lastname.to_string();
        let email = user.email.to_string();

        let client = Client::connect("localhost", 27017)
            .ok().expect("Error establishing connection.");

        let coll = client.db("rusty").collection("users");

        match coll.insert_one(doc! {
            "firstname" => firstname,
            "lastname" => lastname,
            "email" => email
        }, None) {
            Ok(_) => (StatusCode::Ok, "Item saved!"),
            Err(e) => return _res.send(format!("{}", e))
        }
    });
    router.delete("/users/:id", middleware! { |_req, _res|
        let client = Client::connect("localhost", 27017)
            .ok().expect("Failed to initialize standalone client.");

        let coll = client.db("rusty").collection("users");

        let object_id = _req.param("id").unwrap();
        let id = match ObjectId::with_string(object_id) {
            Ok(oid) => oid,
            Err(e) => return _res.send(format!("{}", e))
        };
        match coll.delete_one(doc! {"_id" => id}, None) {
            Ok(_) => (StatusCode::Ok, "Item deleted!"),
            Err(e) => return _res.send(format!("{}", e))
        }
    });
    server.utilize(router);
    server.listen("0.0.0.0:3000").unwrap();
}

简短的版本是肯定的,它会,因为你的库 return Results,这基本上独立于你决定使用的任何框架。

长答案是肯定的,但要小心。作为官方的 mongoDB 客户端(您正在使用的客户端)和几乎所有替代方案都具有完全阻塞的操作(从您调用 find() 到获得 Result ,主线程被阻塞),这意味着您的整个事件循环可能会在该时间间隔内阻塞。

社区似乎没有努力改进底层 mongo C 库,或者将所有操作转移到另一个线程并提供进出该线程的数据访问,因此您缺少选择现在,可悲的是。

Mongodb 在其最新版本上允许在其核心上使用多线程。 因此,r2d2_mongodb 已于 2019 年 12 月弃用。 然后应该可以在连接上使用 RwLock 并将其传递给 actix。