Skapa en Rust-konsolapp med Azure DocumentDB

I den här guiden skapar du ett Rust-konsolprogram för att ansluta till ett Azure DocumentDB-kluster. Guiden beskriver hur du konfigurerar utvecklingsmiljön med hjälp av azure_identity lådan från Azure SDK för Rust för att autentisera och hantera dokument i databasen.

Förutsättningar

  • En prenumeration på Azure

  • Ett befintligt Azure DocumentDB-kluster

  • Microsoft Entra-autentisering har konfigurerats för klustret och din identitet har tilldelats root roll.

  • Senaste versionen av Python.

Konfigurera konsolprogrammet

Skapa sedan ett nytt konsolprogramprojekt och importera de bibliotek som behövs för att autentisera till klustret.

  1. Skapa ett nytt Rust-projekt med .cargo new

    cargo new mongodb-app
    cd mongodb-app
    
  2. azure_core Lägg till lådan i dina beroenden.

    cargo add azure_core
    
  3. azure_identity Lägg till lådan för autentisering.

    cargo add azure_identity
    
  4. Lägg till drivrutinslådan mongodb för att interagera med klustret.

    cargo add mongodb
    
  5. För asynkrona åtgärder lägger du även till de stödjande tokio, futuresoch serde crates.

    cargo add tokio --features full
    cargo add futures
    cargo add serde --features derive
    

Anslut till klustret

Använd nu Azure.Identity biblioteket för att få en TokenCredential som du kan använda för att ansluta till din kluster. Den officiella MongoDB-drivrutinen har ett särskilt gränssnitt som måste implementeras för att hämta token från Microsoft Entra för användning vid anslutning till klustret.

  1. Öppna filen main.rs och importera nödvändiga lådor och moduler.

    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};
    
  2. Skapa den huvudsakliga asynkrona funktionen med nödvändig felhantering.

    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
    
        Ok(())
    }
    
  3. Skapa en ny instans av struct azure_identity::DefaultAzureCredential.

    let credential = DefaultAzureCredential::new()?;
    
  4. Skapa ett återanrop för autentiseringsuppgifter för att hantera tokenbegäranden från MongoDB-klienten.

    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();
    
  5. Definiera en enhetlig resursindikator (URI) från klustret med dess namn, schema och den globala slutpunkten.

    let cluster_name = "<azure-documentdb-cluster-name>";
    
    let uri = format!(
        "mongodb+srv://{}.global.mongocluster.cosmos.azure.com/",
        cluster_name
    );
    
  6. Skapa en mongodb::ClientOptions instans med hjälp av bästa praxis-konfiguration, din URI och autentiseringsuppgiftsåterkoppling.

    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);
    
  7. Skapa en ny instans av mongodb::Client med hjälp av de konstruerade inställningarna.

    let client = Client::with_options(client_options)?;
    
    println!("Client created");
    

Utföra vanliga åtgärder

Använd slutligen det officiella biblioteket för att utföra vanliga uppgifter med databaser, samlingar och dokument. Här använder du samma klasser och metoder som du skulle använda för att interagera med MongoDB eller DocumentDB för att hantera dina samlingar och objekt.

  1. Skapa en Rust-struct för att representera dina Product dokument med serde serialiseringsstöd.

    #[derive(Serialize, Deserialize, Debug)]
    struct Product {
        _id: String,
        category: String,
        name: String,
        quantity: i32,
        price: f64,
        clearance: bool,
    }
    
  2. Hämta en referens till din databas med namn.

    let database = client.database("<database-name>");
    
    println!("Database pointer created");
    
  3. Hämta en referens till din samling.

    let collection = database.collection::<Product>("<collection-name>");
    
    println!("Collection pointer created");
    
  4. Skapa ett dokument med och collection.update_oneupsert det till samlingen.

    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);
    
  5. Läs ett specifikt dokument från samlingen med hjälp av collection.find_one och ett filter.

    let document = collection
        .find_one(doc! { "_id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb" })
        .await?;
    
    println!("Read document _id:\t{:#?}", document.unwrap()._id);
    
  6. Fråga efter flera dokument som matchar ett filter med hjälp av 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);
    }