Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
In this guide, you create a Rust console application to connect to an Azure Cosmos DB for MongoDB vCore cluster. The guide covers setting up your development environment, using the azure_identity
crate from the Azure SDK for Rust to authenticate, and managing documents within the database.
Prerequisites
- An existing Azure Cosmos DB for MongoDB (vCore) cluster.
The latest version of the Azure CLI in Azure Cloud Shell.
- If you prefer to run CLI reference commands locally, sign in to the Azure CLI by using the
az login
command.
- If you prefer to run CLI reference commands locally, sign in to the Azure CLI by using the
Microsoft Entra authentication configured for the cluster with your identity granted
dbOwner
role.- To enable Microsoft Entra authentication, review the configuration guide.
Latest version of Python.
Configure your console application
Next, create a new console application project and import the necessary libraries to authenticate to your cluster.
Create a new Rust project using
cargo new
.cargo new cosmos-mongodb-app cd cosmos-mongodb-app
Add the
azure_core
crate to your dependencies.cargo add azure_core
Add the
azure_identity
crate for authentication.cargo add azure_identity
Add the
mongodb
driver crate to interact with your cluster.cargo add mongodb
For async operations, also add the supporting
tokio
,futures
, andserde
crates.cargo add tokio --features full cargo add futures cargo add serde --features derive
Connect to the cluster
Now, use the Azure.Identity
library to get a TokenCredential
to use to connect to your cluster. The official MongoDB driver has a special interface that must be implemented to obtain tokens from Microsoft Entra for use when connecting to the cluster.
Open your main.rs file and import the necessary crates and modules.
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};
Create the main async function with the necessary error handling.
#[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { Ok(()) }
Create a new instance of struct
azure_identity::DefaultAzureCredential
.let credential = DefaultAzureCredential::new()?;
Create a credential callback to handle token requests from the MongoDB client.
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.windows.net/.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();
Define a uniform resource indicator (URI) from your cluster using its name, scheme, and the global endpoint.
let cluster_name = "<azure-cosmos-db-mongodb-vcore-cluster-name>"; let uri = format!( "mongodb+srv://{}.global.mongocluster.cosmos.azure.com/", cluster_name );
Construct a
mongodb::ClientOptions
instance using best practices configuration, your URI, and the credential callback.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);
Create a new instance of
mongodb::Client
using the constructed settings.let client = Client::with_options(client_options)?; println!("Client created");
Perform common operations
Finally, use the official library to perform common tasks with databases, collections, and documents. Here, you use the same classes and methods you would use to interact with MongoDB or DocumentDB to manage your collections and items.
Create a Rust struct to represent your
Product
documents withserde
serialization support.#[derive(Serialize, Deserialize, Debug)] struct Product { _id: String, category: String, name: String, quantity: i32, price: f64, clearance: bool, }
Get a reference to your database by name.
let database = client.database("<database-name>"); println!("Database pointer created");
Get a reference to your collection.
let collection = database.collection::<Product>("<collection-name>"); println!("Collection pointer created");
Create a document using
collection.update_one
and upsert it into the collection.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);
Read a specific document from the collection using
collection.find_one
and a filter.let document = collection .find_one(doc! { "_id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb" }) .await?; println!("Read document _id:\t{:#?}", document.unwrap()._id);
Query for multiple documents matching a filter using
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); }