Rust连接MongoDB出现类型不匹配错误,求解决方案
Rust连接MongoDB编译错误:类型不匹配问题
编写的Rust连接MongoDB代码在执行cargo run时,if语句处触发编译错误,错误提示为Expected Result<Option<Value>, Error>, found Result<Option<&...>, ...>,需要修复该问题以让database_connection()函数能被Rocket路由调用。
原代码
use std::iter::FilterMap; use rocket::serde::json::{json, Value}; use futures::{StreamExt}; use mongodb::{bson::doc, options::ClientOptions, Client}; use bson::{Document}; use warp::body::json; /** * MongoDB client */ #[tokio::main] pub async fn database_connection(key: &str, value: &str) -> Result<Option<Value>, mongodb::error::Error> { // uri to connect to the database let uri = "mongodb://admin:adminpassword@localhost:27017"; // options to connect to the database let mut client_options = ClientOptions::parse(uri) .await?; // Create a new client and connect to the server with the given options let client = Client::with_options(client_options)?; //Connect to the BinGo! database let material = client.database("BinGo!"); // Search thrue a collection let collection = material.collection::<Document>("bingo_materials"); let filter = doc! { key: value }; print!("Making the query to the database...\n"); println!("Filter: {:#?}", filter); print!("-------------------------\n"); let mut cursor = collection. find(filter, None) .await?; if let Some(result) = cursor.next().await { println!("{:#?}", result); let result_json: &Result<Document, mongodb::error::Error> = &result; return Ok(Some(result_json)); } else { return Ok(None); } }
错误详情
error[E0308]: mismatched types --> src/databases.rs:57:5 | 25 | pub async fn database_connection(key: &str, value: &str) -> Result<Option<Value>, mongodb::error::Error> { | -------------------------------------------- expected `Result<std::option::Option<rocket_dyn_templates::tera::Value>, mongodb::error::Error>` because of return type ... 57 | / if let Some(result) = cursor.next().await { 58 | | println!("{:#?}", result); 59 | | let result_json: &Result<Document, mongodb::error::Error> = &result; 60 | | return Ok(Some(result_json)); 61 | | }else{ 62 | | return Ok(None); 63 | | } | |_____^ expected `Result<Option<Value>, Error>`, found `Result<Option<&...>, ...>` | = note: expected enum `Result<std::option::Option<rocket_dyn_templates::tera::Value>, mongodb::error::Error>` found enum `Result<std::option::Option<&Result<bson::Document, mongodb::error::Error>>, _>`
解决方法
错误原因分析
- 类型不匹配:函数声明返回
Result<Option<rocket::serde::json::Value>, mongodb::error::Error>,但代码中返回的是&Result<Document, mongodb::error::Error>,两者类型完全不兼容。 - 错误处理缺失:
cursor.next().await返回的Some(result)中的result本身是Result<Document, mongodb::error::Error>,需要先处理这个层级的错误,而不是直接取引用。 - 类型转换缺失:需要将MongoDB的
bson::Document转换为Rocket的json::Value类型。
修复步骤
- 处理
cursor.next().await返回的Result错误:使用?操作符提取Document。 - 将
Document转换为rocket::serde::json::Value:利用bson::to_value方法完成转换(需确保bson依赖启用serde特性)。 - 移除不必要的引用,直接返回符合函数声明的类型。
- 移除
#[tokio::main]宏:Rocket自身会管理异步运行时,无需单独标注。
修正后的代码
use rocket::serde::json::Value; use futures::StreamExt; use mongodb::{bson::doc, options::ClientOptions, Client}; use bson::{Document, to_value}; /** * MongoDB client */ pub async fn database_connection(key: &str, value: &str) -> Result<Option<Value>, mongodb::error::Error> { // 数据库连接URI let uri = "mongodb://admin:adminpassword@localhost:27017"; // 解析客户端连接选项 let client_options = ClientOptions::parse(uri).await?; // 创建客户端并连接 let client = Client::with_options(client_options)?; // 连接到BinGo!数据库 let db = client.database("BinGo!"); // 获取bingo_materials集合 let collection = db.collection::<Document>("bingo_materials"); // 构建查询过滤器 let filter = doc! { key: value }; println!("Making the query to the database..."); println!("Filter: {:#?}", filter); println!("---------------------------------"); // 执行查询获取游标 let mut cursor = collection.find(filter, None).await?; // 处理游标结果 if let Some(doc_result) = cursor.next().await { // 处理单条文档的查询错误 let doc = doc_result?; // 将Document转换为Rocket的JSON Value let json_value = to_value(&doc)?; Ok(Some(json_value)) } else { // 无匹配文档 Ok(None) } }
依赖配置说明
确保Cargo.toml中的bson依赖启用serde特性,同时配置好Rocket等依赖:
[dependencies] bson = { version = "2.0", features = ["serde"] } rocket = { version = "0.5", features = ["json"] } mongodb = "2.0" futures = "0.3" tokio = { version = "1.0", features = ["full"] }
内容的提问来源于stack exchange,提问作者Elia Todescato
相关产品推荐
相关产品推荐

