【问题标题】:Does the Rust Actix Web support MongoDB?Rust Actix Web 是否支持 MongoDB?
【发布时间】:2020-01-05 17:13:45
【问题描述】:

我有一个新的 Rust Programming 后端学习。 从 Web 框架开始。 由于我想在 MongoDB 中使用 Rust 后端,所以我有 Nickel 的示例代码。 反正我也看到有Actix Web Framework。

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

以下示例为 MongoDB 提供 Nickel。

//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();
}

【问题讨论】:

    标签: mongodb rust rust-actix actix-web


    【解决方案1】:

    简短的版本是肯定的,它会的,因为您的库返回 Results,这基本上与您决定使用的任何框架无关。

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

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

    【讨论】:

    • 非常感谢,您的回答对我很有用。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2021-08-20
      • 2021-10-14
      • 1970-01-01
      • 1970-01-01
      • 2021-10-16
      • 1970-01-01
      • 2016-07-07
      • 2020-09-14
      • 2020-08-06
      相关资源
      最近更新 更多