Rust操作MongoDB时游标调用try_next()方法报错‘未找到该方法’的求助
嗨,我看到你遇到的问题了——别担心,这不是你的模型定义有问题,而是Rust的trait作用域规则在搞鬼!
错误提示里已经给了关键线索:items from traits can only be used if the trait is in scope,意思是这个try_next方法不是mongodb::Cursor自带的,而是来自一个扩展trait,你需要手动把它引入到代码的作用域里才能调用。
1. 引入必要的扩展trait
try_next方法属于futures::stream::TryStreamExt这个trait,所以你只需要在代码顶部加上这一行:
use futures::stream::TryStreamExt;
如果你还没在Cargo.toml里添加相关依赖(从错误日志看你已经有futures-util了,它包含了futures核心功能,所以大概率已经满足),可以确认一下依赖项里有类似条目:
[dependencies] futures = "0.3" mongodb = "2.0" # 替换为你实际使用的版本 serde = { version = "1.0", features = ["derive"] }
2. 确认你的模型trait没问题
你担心的DeserializeOwned、Unpin、Send、Sync这些trait,其实不需要手动给结构体加derive:
DeserializeOwned:只要你的结构体实现了Deserialize(你已经加了#[derive(Deserialize)]),且所有字段都是“owned”类型(非引用),编译器会自动为它实现这个trait;Unpin、Send、Sync:只要结构体里的每个字段都实现了这些trait(比如FieldElement、IpAddr、f32、bool这些默认都满足),你的Score结构体就会自动继承这些trait。
所以你的模型定义完全没问题,不用修改。
3. 完整的示例代码
这里给你一个可以直接运行的读取数据示例:
use futures::stream::TryStreamExt; use mongodb::{Client, Collection, error::Result}; use serde::{Deserialize, Serialize}; use std::net::IpAddr; // 假设你的FieldElement是这样定义的(确保它实现了serde的序列化/反序列化) #[derive(Clone, Debug, Deserialize, Serialize)] pub struct FieldElement { // 你的字段定义 } #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Score { pub address: FieldElement, pub score: f32, pub cheat: bool, pub ip_addr: IpAddr, } async fn get_scores() -> Result<()> { // 连接MongoDB let client = Client::with_uri_str("mongodb://localhost:27017").await?; let db = client.database("your_db_name"); let collection: Collection<Score> = db.collection("scores"); // 查询数据并迭代 let mut cursor = collection.find(None, None).await?; while let Some(toto) = cursor.try_next().await? { println!("score: {}", toto.score); } Ok(()) }
为什么会出现这个错误?
Rust的设计里,扩展trait的方法不会自动全局可用——只有当你把对应的trait引入到当前作用域(用use语句),编译器才能识别到这些方法。mongodb::Cursor实现了TryStream trait,而TryStreamExt是给TryStream提供的扩展方法集合,try_next就是其中之一,所以必须显式引入这个trait才能调用它。
这样修改之后,你的游标迭代代码应该就能正常运行了!
备注:内容来源于stack exchange,提问作者Th0rgal

