本指南创建 Rust 控制台应用程序以连接到 Azure DocumentDB 群集。 本指南介绍了如何设置开发环境,使用 Azure SDK for Rust 中的 azure_identity crate 进行身份验证,以及管理数据库中的文档。
先决条件
Azure 订阅服务
- 如果没有 Azure 订阅,请创建 试用版
现有的 Azure DocumentDB 群集
- 如果没有群集,请 创建新群集
如需在本地运行 CLI 参考命令,请安装 Azure CLI。 如果在 Windows 或 macOS 上运行,请考虑在 Docker 容器中运行 Azure CLI。 有关详细信息,请参阅如何在 Docker 容器中运行 Azure CLI。
如果使用的是本地安装,请使用 az login 命令登录到 Azure CLI。 若要完成身份验证过程,请遵循终端中显示的步骤。 有关其他登录选项,请参阅使用 Azure CLI 登录。
出现提示时,请在首次使用时安装 Azure CLI 扩展。 有关扩展的详细信息,请参阅 将扩展与 Azure CLI 配合使用。
运行az version命令,以查看已安装的版本和依赖库。 若要升级到最新版本,请运行az upgrade。
配置控制台应用程序
接下来,创建新的控制台应用程序项目,并导入必要的库以向群集进行身份验证。
使用
cargo new.. 创建新的 Rust 项目。cargo new mongodb-app cd mongodb-app将
azure_coreCrate 添加到依赖项。cargo add azure_core添加
azure_identityCrate 进行身份验证。cargo add azure_identity添加
mongodb驱动程序 Crate 以与群集交互。cargo add mongodb对于异步操作,还要添加支持
tokio、futures和serdeCrate。cargo add tokio --features full cargo add futures cargo add serde --features derive
连接至群集
现在,使用 Azure.Identity 库获取一个 TokenCredential,以用于连接到您的群集。 官方 MongoDB 驱动程序具有一个特殊接口,必须实现该接口,以便从 Microsoft Entra 获取令牌,以便在连接到群集时使用。
打开 main.rs 文件并导入必要的 Crate 和模块。
use azure_core::credentials::TokenCredential; use azure_identity::DefaultAzureCredential; use futures::{FutureExt, TryStreamExt}; use mongodb::{ Client, bson::doc, options::{ AuthMechanism, ClientOptions, Credential, oidc::{self, IdpServerResponse}, }, }; use serde::{Deserialize, Serialize};创建主异步函数,并进行必要的错误处理。
#[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { Ok(()) }创建结构
azure_identity::DefaultAzureCredential的新实例。let credential = DefaultAzureCredential::new()?;创建凭据回调以处理来自 MongoDB 客户端的令牌请求。
let azure_identity_token_credential = Credential::builder() .mechanism(AuthMechanism::MongoDbOidc) .oidc_callback(oidc::Callback::machine(move |_| { let azure_credential = credential.clone(); async move { let access_token = azure_credential .get_token(&["https://ossrdbms-aad.database.chinacloudapi.cn/.default"]) .await .map_err(|e| { mongodb::error::Error::custom(format!("Azure token error: {}", e)) })?; Ok(IdpServerResponse::builder() .access_token(access_token.token.secret().to_owned()) .build()) } .boxed() })) .build() .into();使用群集的名称、方案和全局终结点定义统一的资源指示器(URI)。
let cluster_name = "<azure-cosmos-db-mongodb-vcore-cluster-name>"; let uri = format!( "mongodb+srv://{}.global.mongocluster.cosmos.azure.cn/", cluster_name );使用最佳实践配置、您的 URI 和凭据回调来构造
mongodb::ClientOptions实例。let mut client_options = ClientOptions::parse(uri).await?; client_options.connect_timeout = Some(std::time::Duration::from_secs(120)); client_options.tls = Some(mongodb::options::Tls::Enabled(Default::default())); client_options.retry_writes = Some(true); client_options.credential = Some(azure_identity_token_credential);创建使用已构造设置的新实例
mongodb::Client。let client = Client::with_options(client_options)?; println!("Client created");
执行常见操作
最后,使用官方库对数据库、集合和文档执行常见任务。 在这里,你将使用相同的类和方法与 MongoDB 或 DocumentDB 进行交互来管理集合和项。
创建一个 Rust 结构,用于表示支持
Product序列化的serde文档。#[derive(Serialize, Deserialize, Debug)] struct Product { _id: String, category: String, name: String, quantity: i32, price: f64, clearance: bool, }按名称获取对数据库的引用。
let database = client.database("<database-name>"); println!("Database pointer created");获取对集合的引用。
let collection = database.collection::<Product>("<collection-name>"); println!("Collection pointer created");使用
collection.update_one创建文档,并将其更新插入到集合中。let document = Product { _id: "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb".to_string(), category: "gear-surf-surfboards".to_string(), name: "Yamba Surfboard".to_string(), quantity: 12, price: 850.00, clearance: false, }; let response = collection .update_one( doc! { "_id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb" }, doc! { "$set": mongodb::bson::to_document(&document)? }, ) .upsert(true) .await?; println!("Documents upserted count:\t{}", response.modified_count);使用
collection.find_one筛选器从集合中读取特定文档。let document = collection .find_one(doc! { "_id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb" }) .await?; println!("Read document _id:\t{:#?}", document.unwrap()._id);使用
collection.find查询匹配筛选条件的多个文档。let filter = doc! { "category": "gear-surf-surfboards" }; let mut cursor = collection.find(filter).await?; while let Some(document) = cursor.try_next().await? { println!("Found document:\t{:#?}", document); }