尝试使用 MongoDB 的官方 Rust 驱动程序(alpha 版)(2)(使用结构体)
概述
本次实现使用结构体进行插入和查找操作。同时,需要考虑当结构体的某些字段没有数据时的处理方式。
环境
-
- Windows 10
-
- MongoDB Community版 4.2.2
-
- rust 1.40.0
-
- MongoDB rust
ドライバー 0.9.0 (alpha版)
https://crates.io/crates/mongodb
https://github.com/mongodb/mongo-rust-driver
bson 0.14.0
https://crates.io/crates/bson
https://github.com/mongodb/bson-rust
Rustのクレートなど
serde 1.0.104
进行实施
向Cargo.toml中的dependencies部分添加
[dependencies]
mongodb ="0.9.0"
bson = "0.14.0"
serde = "1.0.104"
请用中文来解释这个词”コード”。
use mongodb::{error::Result, options::{ClientOptions}, Client};
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
pub struct Coll {
pub item1: f64,
pub item2: i64,
pub item3: String
}
fn main() {
let client = connect_mongo().expect("failed to connect");
insert_docs(&client).expect("failed to insert docs");
find_all_docs(&client).expect("failed to find all docs");
}
fn connect_mongo() -> Result<Client> {
let mut client_options = ClientOptions::parse("mongodb://localhost:27017")?;
client_options.app_name = Some("My App".to_string());
let client = Client::with_options(client_options)?;
Ok(client)
}
fn insert_docs(client: &Client) -> Result<()> {
let collection = client.database("test").collection("coll");
let col_data = Coll{
item1: 12.3,
item2: 456,
item3: String::from("string data")
};
let serialized_data = bson::to_bson(&col_data)?;
if let bson::Bson::Document(document) = serialized_data {
collection.insert_one(document, None)?;
} else {
println!("Error converting the BSON object into a MongoDB document");
}
Ok(())
}
fn find_all_docs(client: &Client) -> Result<()> {
let collection = client.database("test").collection("coll");
let cursor = collection.find(None, None)?;
for result in cursor {
match result {
Ok(document) => {
let coll = bson::from_bson::<Coll>(bson::Bson::Document(document))?;
println!("item1: {}, item2: {}, item3: {}", coll.item1, coll.item2, coll.item3);
}
Err(e) => return Err(e.into()),
}
}
Ok(())
}
構造体に値を代入するには、bson::from_bson::を使用しています。
cargo run
Running `target\debug\mongorust.exe`
item1: 12.3, item2: 456, item3: string data
我会创建一些缺少字段的数据来测试。
mongo
> db.coll.insert({item1:11})
WriteResult({ "nInserted" : 1 })
> db.coll.find()
{ "_id" : ObjectId("5e2644d000a7d017003530ee"), "item1" : 12.3, "item2" : NumberLong(456), "item3" : "string data" }
{ "_id" : ObjectId("5e264597469b580a90779fbe"), "item1" : 11 }
再次运行Rust程序
cargo run
Running `target\debug\mongorust.exe`
item1: 12.3, item2: 456, item3: string data
thread 'main' panicked at 'failed to find all docs: Error { kind: BsonDecode(ExpectedField("item2")) }', src\libcore\result.rs:1165:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
error: process didn't exit successfully: `target\debug\mongorust.exe` (exit code: 101)
如果结构体的字段数据不存在,则会出现上述错误。因此,将结构体的数据类型设置为Option类型。另外,我们来看看在插入时插入None会发生什么。
use mongodb::{error::Result, options::{ClientOptions}, Client};
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
pub struct Coll {
pub item1: f64,
pub item2: Option<i64>,
pub item3: Option<String>
}
fn main() {
let client = connect_mongo().expect("failed to connect");
insert_docs(&client).expect("failed to insert docs");
find_all_docs(&client).expect("failed to find all docs");
}
fn connect_mongo() -> Result<Client> {
let mut client_options = ClientOptions::parse("mongodb://localhost:27017")?;
client_options.app_name = Some("My App".to_string());
let client = Client::with_options(client_options)?;
Ok(client)
}
fn insert_docs(client: &Client) -> Result<()> {
let collection = client.database("test").collection("coll");
let col_data = Coll{
item1: 78.9,
item2: None,
item3: Some(String::from("string data2"))
};
let serialized_data = bson::to_bson(&col_data)?;
if let bson::Bson::Document(document) = serialized_data {
collection.insert_one(document, None)?;
} else {
println!("Error converting the BSON object into a MongoDB document");
}
Ok(())
}
fn find_all_docs(client: &Client) -> Result<()> {
let collection = client.database("test").collection("coll");
let cursor = collection.find(None, None)?;
for result in cursor {
match result {
Ok(document) => {
let coll = bson::from_bson::<Coll>(bson::Bson::Document(document))?;
print!("item1: {}", coll.item1);
match coll.item2 {
Some(v) => print!(" item2: {}", v),
None => {}
}
match coll.item3 {
Some(v) => print!(" item3: {}", v),
None => {}
}
println!()
}
Err(e) => return Err(e.into()),
}
}
Ok(())
}
我使用None将item2插入了。
我使用了一个条件,在find中当结构体的每个字段为None时不打印。除了使用match来操作每个字段,我想不到其他的方法。
cargo run
Running `target\debug\mongorust.exe`
item1: 12.3 item2: 456 item3: string data
item1: 11
item1: 78.9 item3: string data2
由于意图之外的字段是空的,所以它没有被打印出来。
接下来我们将在Mongo中进行确认。
mongo
> db.coll.find()
{ "_id" : ObjectId("5e2644d000a7d017003530ee"), "item1" : 12.3, "item2" : NumberLong(456), "item3" : "string data" }
{ "_id" : ObjectId("5e264597469b580a90779fbe"), "item1" : 11 }
{ "_id" : ObjectId("5e269159008ba689009e7150"), "item1" : 78.9, "item2" : null, "item3" : "string data2" }
在 Rust 中,因为使用了 None 插入,导致字段的值变成了 null。目前还不清楚有没有方法可以不插入结构体中已定义的字段。
最后
我对Rust中的错误处理和枚举不太理解,无法解释代码中的一些部分。
对于MongoDB的CRUD,aggregate、update、delete等功能还没有完全掌握,但似乎并不太难。然而,我还没找到事务功能。
链接
试用 MongoDB 官方 Rust 驱动程序(Alpha 版)。