0

我有一个新的 Rust Programming 后端学习。从 Web 框架开始。因为我想在 MongoDB 中使用 Rust 后端,所以我有 Nickel 的示例代码。无论如何,我也看到有 Actix Web 框架。

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

2 回答 2

4

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

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

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

于 2019-09-12T12:02:45.103 回答
3

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

于 2020-01-05T09:13:45.497 回答