宇野  和也

宇野 和也

1638702300

RustアプリケーションをMongoDBクラスターに接続する

このクイックスタートの投稿は、RustアプリケーションをMongoDBクラスターに接続するのに役立ちます。次に、コレクションに対してCreate、Read、Update、およびDelete(CRUD)操作を実行する方法を示します。最後に、serdeを使用してMongoDBのBSONドキュメントとRust構造体の間をマッピングする方法について説明します。

シリーズツールとバージョン

このシリーズは、Rustツールチェーンの最新バージョン(v1.44 +)がインストールされており、Rust構文に慣れていることを前提としています。また、コマンドラインとお気に入りのコードエディタの使用にかなり慣れていることも前提としています。

Rustは、さまざまなタスクに適した、高性能でメモリ使用量の少ない強力なシステムプログラミング言語です。現在、データを操作するためのニッチな言語ですが、その人気は急速に高まっています。

Rustを使用していて、MongoDBを使用したい場合は、このブログシリーズから始めることができます。次の方法を紹介します。

MongoDBRustドライバーをインストールします。Rustドライバーは、 MongoDBクラスターとの通信を可能にするmongodbクレートです。

MongoDBインスタンスに接続します。

データベースでドキュメントを作成、読み取り、更新、削除(CRUD)します。

シリーズの後半のブログ投稿では、ストリームの変更トランザクション、データに対して高度なクエリを実行できる驚くべき集約パイプライン機能などについて説明します。

データベースの作成

MongoDB Atlasを使用してMongoDBクラスターをホストするため、MongoDB自体の構成方法について心配する必要はありません。

AtlasでM0クラスターを使い始めましょう 。これは永久に無料で、このブログシリーズの手順を試す最も簡単な方法です。支払いの詳細を提供する必要もありません。

新しいクラスターを作成し、サンプルデータをロードする必要があります。私のすばらしい同僚であるMaxime Beugnetが、 役立つビデオチュートリアルを作成しました が、以下の手順についても説明します。

MongoDBホームページの「無料で開始」をクリックします。

詳細を入力するか、Googleアカウントをお持ちの場合は、Googleアカウントでサインアップしてください。

利用規約に同意する

スタータークラスターを作成します。

慣れているものと同じクラウドプロバイダーを選択するか、そのままにしておきます。自分に合った地域を選んでください。

必要に応じて、クラスターの名前を変更できます。私は自分のことを「RustQuickstart」と呼んでいます。

クラスタがプロビジョニングされるまでに数分かかるため、待っている間に次のステップに進むことができます。

プロジェクトを開始する

ターミナルで、コーディングプロジェクトを保存しているディレクトリに移動し、次のコマンドを実行します。

cargo new --bin rust_quickstart

これによりrust_quickstart、ほぼ空の新しいプロジェクトを含むという新しいディレクトリが作成されます。ディレクトリでCargo.toml[dependencies]セクションを開いて変更し、次のようにします。

[dependencies]2mongodb = "1.2.0"

これで、以下を実行して依存関係をダウンロードして構築できます。

cargo run

ダウンロードおよびコンパイルされた多くの依存関係が表示されるはずです。心配しないでください。これのほとんどは、初めて実行したときにのみ発生します。最後に、すべてがうまくいけば、「He​​llo、World!」と表示されます。コンソールで。

MongoDBインスタンスをセットアップします

MongoDBクラスターは、しばらくの間セットアップされて実行されているはずです。これで、先に進んで、次のステップのためにデータベースをセットアップすることができます。

Atlas Webインターフェイスでは、画面の左下に「はじめに」という緑色のボタンが表示されます。それをクリックすると、データベースをセットアップするための手順のチェックリストが表示されます。リスト内の各項目(オプションの「サンプルデータのロード」項目を含む)をクリックすると、セットアップの手順がわかります。

ユーザーを作成する

「はじめに」の手順に従って、「任意のデータベースへの読み取りおよび書き込みアクセス権」を持つユーザーを作成します。あなたはそれにあなたの選んだユーザー名とパスワードを与えることができます-それらをメモしてください、あなたはすぐにそれらを必要とするでしょう。「安全なパスワードの自動生成」ボタンを使用して、後で接続文字列に安全に貼り付けることもできる長いランダムパスワードがあることを確認します。

IPアドレスを許可する

機密データを含むアプリをデプロイする場合は、データベースに接続する必要のあるサーバーのIPアドレスのみを許可する必要があります。[IPアドレスの追加]ボタンをクリックし、[現在のIPアドレスの追加]をクリックして、最後に[確認]をクリックします。セキュリティを強化するために、アクセスリストエントリに時間制限を設定することもできます。IPアドレスが変更される場合があるため、このチュートリアル中にMongoDBクラスターに接続できなくなった場合は、戻ってこれらの手順を繰り返してください。

MongoDBに接続する

これで、このチュートリアルの要点がわかりました。RustコードをMongoDBデータベースに接続することです。「はじめに」チェックリストの最後のステップは、「クラスターに接続する」です。「アプリケーションを接続する」を選択します。

通常、表示されるダイアログでは、[ドライバー]メニューで[Rust]を選択しますが、Rustドライバーはリリースされたばかりであるため、リストに含まれていない可能性があります。バージョンが「3.6以降」の「Python」を選択する必要があります。

手順2で[接続文字列のみ]が強調表示されていることを確認し、[コピー]ボタンを押してURLをペーストボードにコピーします(一時的にテキストファイルに保存するだけで問題ありません)。ユーザー名とパスワードを保存したのと同じ場所に貼り付けます。URLには<password> パスワードのプレースホルダーがあることに注意してください。ここにパスワードを貼り付けて、「<」および「>」文字を含むプレースホルダー全体を置き換える必要があります。

Rustプロジェクトに戻りmain.rs、内容を開いて次のように置き換えます。

use mongodb::bson::{self, doc, Bson};
use std::env;
use std::error::Error;
use tokio;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
   // Load the MongoDB connection string from an environment variable:
   let client_uri =
      env::var("MONGODB_URI").expect("You must set the MONGODB_URI environment var!");

   // A Client is needed to connect to MongoDB:
   // An extra line of code to work around a DNS issue on Windows:
   let options =
      ClientOptions::parse_with_resolver_config(&client_uri, ResolverConfig::cloudflare())
         .await?;
   let client = mongodb::Client::with_options(options)?;

   // Print the databases in our MongoDB cluster:
   println!("Databases:");
   for name in client.list_database_names(None, None).await? {
      println!("- {}", name);
   }

   Ok(())
}

これを実行するには、MONGODB_URI環境変数を上記で取得した接続文字列に設定する必要があります。プラットフォームに応じて、ターミナルウィンドウで次のいずれかを実行します。

# Unix (including MacOS):
export MONGODB_URI='mongodb+srv://yourusername:yourpasswordgoeshere@rustquickstart-123ab.mongodb.net/test?retryWrites=true&w=majority'

# Windows CMD shell:
set MONGODB_URI='mongodb+srv://yourusername:yourpasswordgoeshere@rustquickstart-123ab.mongodb.net/test?retryWrites=true&w=majority'

# Powershell:
$Env:MONGODB_URI='mongodb+srv://yourusername:yourpasswordgoeshere@rustquickstart-123ab.mongodb.net/test?retryWrites=true&w=majority'

それが済んだら、cargo runこのコードを実行できます。結果は次のようになります。

$ cargo run
   Compiling rust_quickstart v0.0.1 (/Users/judy2k/development/rust_quickstart)
   Finished dev [unoptimized + debuginfo] target(s) in 3.35s
   Running `target/debug/rust_quickstart`
Database: sample_airbnb
Database: sample_analytics
Database: sample_geospatial
Database: sample_mflix
Database: sample_supplies
Database: sample_training
Database: sample_weatherdata
Database: admin
Database: local

おめでとう!RustプログラムをMongoDBに接続し、クラスター内のデータベースを一覧表示しました。このリストが表示されない場合は、サンプルデータをクラスターに正常にロードしていない可能性があります。このコマンドを実行すると上記のリストが表示されるまで、いくつかの手順に戻る必要があります。

BSON-MongoDBがデータを理解する方法

データベースのクエリと更新を進める前に、BSONの概要とMongoDBとの関係を理解し​​ておくと便利です。BSONは、MongoDBがすべてのデータを保存するために使用するバイナリデータ形式です。BSONは、MongoDBクエリ言語と集計パイプラインで使用される形式でもあります(これらについては後で説明します)。

これはJSONに類似しており、数値、文字列、配列、オブジェクト(BSONではドキュメントと呼ばれます)など、すべて同じコアタイプを処理しますが、BSONはJSONよりも多くのタイプをサポートします。これには、日付や小数などが含まれ、MongoDBコレクション内のドキュメントを識別するために通常使用される特別なObjectIdタイプがあります。BSONはバイナリ形式であるため、人間が読める形式ではありません。通常、画面に印刷すると、JSONのように印刷されます。

BSONの動的スキーマとRustの静的型システムが一致しないため、RustでBSONを処理するのは難しい場合があります。幸い、 bsonクレートは、doc!BSONドキュメントを生成するためのマクロなど、BSONデータを処理するための便利なツールをいくつか提供し、Rust構造体とBSONデータの間でシリアル化および逆シリアル化する機能のserdeを実装します。

doc!マクロを使用してドキュメント構造を作成すると、次のようになります。

let new_doc = doc! {
   "title": "Parasite",
   "year": 2020,
   "plot": "A poor family, the Kims, con their way into becoming the servants of a rich family, the Parks. But their easy life gets complicated when their deception is threatened with exposure.",
   "released": Utc.ymd(2020, 2, 7).and_hms(0, 0, 0),
};

println!の値をnew_docコンソールに出力するために使用する場合は、次のように表示されます。

{ title: "Parasite", year: 2020, plot: "A poor family, the Kims, con their way into becoming the servants of a rich family, the Parks. But their easy life gets complicated when their deception is threatened with exposure.", released: Date("2020-02-07 00:00:00 UTC") }

(ちなみに、寄生虫は絶対に素晴らしい映画です。2020年にリリースされたため、使用するデータベースにはまだ含まれていませんが、データセットは2015年に最後に更新されました。)

上記の出力はJSONに少し似ていますが、これはBSONライブラリがDisplayトレイトを実装する方法にすぎません。データは、内部では引き続きバイナリデータとして処理されます。

ドキュメントの作成

次の例はすべて 、Atlasクラスターにロードしたsample_mflixデータセットを使用してい ます。moviesIMDBのデータベースから、1903年にリリースされた映画の全負荷の詳細を含む、と呼ばれる楽しいコレクションが含まれています。

クライアントの タイプを使用すると、クラスタ内のデータベースのリストを取得することができますが、それ以外はあまりありません。実際にデータの操作を開始するには、 クライアントまたはメソッドのいずれかを使用してデータベースを取得する必要があり ます。これは次のセクションで行います。databasedatabase_with_options

前のセクションのコードは、メモリ内にドキュメントを作成します。次に、それを映画データベースに永続化します。MongoDBコレクションで何かを行う前の最初のステップは 、データベースからCollectionオブジェクトを取得すること です。これは次のように行われます。

// Get the 'movies' collection from the 'sample_mflix' database:
let movies = client.database("sample_mflix").collection("movies");

CompassまたはAtlasの[Collections]タブで映画コレクションを閲覧した場合 、ほとんどのレコードには、doc!マクロを使用して上記で作成したドキュメントよりも多くのフィールドがあることがわかります。MongoDBはデフォルトでコレクション内にスキーマを適用しないため、これはまったく問題ありません。読みやすくするためにフィールドの数を減らしました。MongoDBコレクションへの参照を取得したら、このinsert_oneメソッドを使用して単一のドキュメントを挿入できます。

let insert_result = movies.insert_one(new_doc.clone(), None).await?;
println!("New document ID: {}", insert_result.inserted_id);

このinsert_oneメソッドは、Result<InsertOneResult> ドキュメントの挿入に関する問題を特定するために使用できるタイプを返し、MongoDBで新しいドキュメント用に生成されたIDを見つけるために使用できます。このコードをメイン関数に追加すると、実行すると次のようになります。

New document ID: ObjectId("5e835f3000415b720028b0ad")

このコードは、シングルDocumentをコレクションに挿入します。あなたが一括で複数のドキュメントを挿入したい場合、それは使用する方が効率的だ insert_manyとるIntoIteratorコレクションに挿入される書類のを。

コレクションからデータを取得する

コレクションにはParasiteという名前のドキュメントが他にないことがわかっているので、レコードを挿入したときに取得したIDの代わりに、次のコードを使用してタイトルで検索できます。

// Look up one document:
let movie = movies
   .find_one(
      doc! {
            "title": "Parasite"
      },
      None,
   ).await?
   .expect("Missing 'Parasite' document.");
println!("Movie: {}", movie);

このコードは、次のような出力になります。

Movie: { _id: ObjectId("5e835f3000415b720028b0ad"), title: "Parasite", year: 2020, plot: "A poor family, the Kims, con their way into becoming the servants of a rich family, the Parks. But their easy life gets complicated when their deception is threatened with exposure.", released: Date("2020-02-07 00:00:00 UTC") }

上記の出力と非常によく似ていますが、レコードを挿入すると、MongoDBドライバーがこのドキュメントを識別するための一意のObjectIdを生成しました。MongoDBコレクション内のすべてのドキュメントには、固有の_id値があります。一意であることが保証されている値がある場合は、自分で値を指定できます。そうしないと、この場合のように、MongoDBが値を生成します。通常は、自分で明示的に値を設定することをお勧めします。

find_oneの方法は、コレクションから単一のドキュメントを取得するのに便利ですが、多くの場合、あなたは複数のレコードを検索する必要があります。この場合、findメソッドが必要になります。このメソッドは、この呼び出しと同様のオプションを取りますが、を返しますResult<Cursor>Cursor返されたデータのリストを反復するために使用されます。

検索操作とそれに付随するフィルタードキュメントは非常に強力であり、おそらくそれらを頻繁に使用します。あなたはより多くの柔軟性を必要とする場合findfind_one提供することができ、その後、私はあなたが上のドキュメントをチェックアウトをお勧めします集約パイプライン の超パワフルで、私の意見であり、MongoDBの最も強力な機能の一つ。このシリーズで、そのトピックについて別のブログ投稿を作成します。楽しみにしています。

コレクション内のドキュメントを更新する

ドキュメントがコレクションに保存されると、さまざまな方法で更新できます。ドキュメントを別のドキュメントに完全に置き換える場合は、find_one_and_replace メソッドを使用できますが、 update_one または update_manyを使用して、ドキュメントの1つ以上の部分を更新するのが一般的 です。個別のドキュメント更新はそれぞれアトミックです。これは、ドキュメント内でデータの一貫性を保つための便利な機能です。update_manyそれ自体は不可分操作ではないことに注意してください。そのためには、バージョン4.0以降のMongoDBで利用可能な(4.2以降のシャードコレクションで利用可能な)マルチドキュメントACIDトランザクションを使用する必要が あります。Rustドライバーのバージョン1.0はまだトランザクションをサポートしていませんが、間もなくリリースされます。

MongoDBで1つのドキュメントを更新するには、2つのBSONドキュメントが必要です。1つ目は、更新するドキュメントを見つけるためのクエリについて説明してい ます。2番目 のドキュメントは、コレクション内のドキュメントに対して実行する更新操作について説明しています。寄生虫の「リリース」日は2020年でしたが、これは米国でのリリースを指していると思います。正しいリリースの年はので、ここでそれに応じてレコードを更新するためのコードだ、2019年でした。

// Update the document:
let update_result = movies.update_one(
   doc! {
      "_id": &insert_result.inserted_id,
   },
   doc! {
      "$set": { "year": 2019 }
   },
   None,
).await?;
println!("Updated {} document", update_result.modified_count);

 

上記を実行すると、「更新された1ドキュメント」が出力されます。そうでない場合は、前に挿入したムービードキュメントに何かが発生しています。多分あなたはそれを削除しましたか?更新によって年の値が正しく更新されたことを確認find_oneするために、プログラムに追加できるコマンドを次に示して、更新されたドキュメントがどのように表示されるかを確認します。

// Look up the document again to confirm it's been updated:
let movie = movies
   .find_one(
      doc! {
            "_id": &insert_result.inserted_id,
      },
      None,
   ).await?
   .expect("Missing 'Parasite' document.");
println!("Updated Movie: {}", &movie);	

これらのコードブロックを実行すると、結果は次のテキストのようになりました。その年が2020年ではなく2019年になったことをどのように示しているかをご覧ください。

Updated 1 document
Updated Movie: { _id: ObjectId("5e835f3000415b720028b0ad"), title: "Parasite", year: 2019, plot: "A poor family, the Kims, con their way into becoming the servants of a rich family, the Parks. But their easy life gets complicated when their deception is threatened with exposure.", released: Date("2020-02-07 00:00:00 UTC") }

コレクションからドキュメントを削除する

上記のセクションでは、コレクション内のドキュメントを作成、読み取り、更新する方法を学びました。プログラムを数回実行したことがあれば、映画「寄生虫」のドキュメントをかなり作成したことでしょう。これで、delete_manyメソッドを使用してそれをクリアする良い機会になりました。MongoDB rustドライバーは、ドキュメントを削除するための3つの方法を提供します。

find_one_and_delete コレクションから1つのドキュメントを削除し、削除されたドキュメントが存在する場合はそれを返します。

delete_one 提供されたフィルターに一致するドキュメントを検索し、最初に見つかったドキュメント(存在する場合)を削除します。

delete_many、ご想像のとおり、提供されたフィルターに一致するドキュメントが検索され、それらがすべて削除されます。

以下のコードでは、delete_many上記のコードをテストするときに複数のレコードを作成した可能性があるため、使用しました。フィルタは名前で映画を検索するだけで、挿入されたすべてのドキュメントに一致して削除されますが、_id値で検索すると、IDが一意であるため、1つだけが削除されます。

フィールドを常にフィルタリングまたは並べ替えている場合は、コレクションの増加に合わせてパフォーマンスを向上させるために、そのフィールドにインデックスを追加することを検討する必要があります。詳細については、MongoDBマニュアルを確認してください。

// Delete all documents for movies called "Parasite":
let delete_result = movies.delete_many(
   doc! {
      "title": "Parasite"
   },
   None,
).await?;
println!("Deleted {} documents", delete_result.deleted_count);

できたね!作成、読み取り、更新、削除の操作は、MongoDBクラスター内のデータにアクセスして管理するために何度も使用するコア操作です。このチュートリアルが提供するテイスターの後で、以下についてさらに詳しく読む価値があります。

すべての読み取り、更新、および削除操作に使用されるクエリドキュメント

MongoDBドライバーがデータにアクセスして変更するために提供するすべての操作を説明するMongoDBクレートドキュメント

bson crateとそれに付随するドキュメントで は、MongoDBから挿入または取得するためのデータを作成およびマッピングする方法について説明しています。

Serdeクレートは、Rustデータ型とBSONをbsonクレートでマッピングするためのフレームワークを提供するため、それを利用する方法を学ぶことが重要です。

serdeデータを構造体にマッピングするために使用する

すぐにはわからないかもしれないbsonクレートの機能の1つは、serdeフレームワークにBSONデータ形式を提供することです。これは、Serdeクレートを利用して、Rustデータ型とBSON型の間でマッピングし、MongoDBで永続化できることを意味します。

これがどのように役立つかの例についてtitleは、new_movieドキュメントのフィールドにアクセスする方法の次の例を参照してください( serdeなし)。

// Working with Document can be verbose:
if let Ok(title) = new_doc.get_str("title") {
   println!("title: {}", title);
} else {
   println!("no title found");
}

上記のコードの最初の行は、の値titleを取得してから、それを文字列として取得しようとします(値が異なるタイプの場合はBson::as_str戻ります None)。かなり多くのエラー処理と変換が関係しています。serdeフレームワークは、受け取る予定のドキュメントに一致するフィールドを使用して、以下のような構造体を定義する機能を提供します。

// You use `serde` to create structs which can serialize & deserialize between BSON:
#[derive(Serialize, Deserialize, Debug)]
struct Movie {
   #[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
   id: Option<bson::oid::ObjectId>,
   title: String,
   year: i32,
}

この構造体をシリアル化および逆シリアル化できることをserdeに通知するマクロSerializeDeserializeマクロの使用に注意してください。このserde 属性は、idstructフィールドをBSONにシリアル化する必要があることをserdeに通知するためにも使用されます_id。これは、MongoDBが呼び出すことを想定しているものです。パラメータはskip_serializing_if = "Option::is_none"またのオプションの値があればというserdeを伝えidているNone、それがすべてでシリアライズするべきではありません。(_id: NoneBSONをMongoDBに提供すると、IDがのドキュメントが保存NULLされますが、提供しない場合は、IDが生成されます。これは、通常、必要な動作です。)

以下のコードMovieは、キャプテンマーベル映画の構造体のインスタンスを作成します。(それは素晴らしい映画ではありませんでしたか?私はその映画が大好きでした!)構造体を作成した後、コレクションに保存する前に、BSONドキュメントに変換する必要があります。これは2つのステップで行われます。最初にbson::to_bsonBsonインスタンスを返す、を使用してBson値に変換されます。次に、それをDocument呼び出すas_documentことによって、具体的にに変換さ れます。unwrap構造体をBSONにシリアル化すると、BSONドキュメントタイプが作成されることをすでに知っているので、この結果を呼び出すのは安全 です。

プログラムがbsonDocumentインスタンスを取得したら、insert_one上記の「ドキュメントの作成」セクションで行ったのとまったく同じ方法で呼び出すことができます。

// Initialize struct to be inserted:
let captain_marvel = Movie {
   id: None,
   title: "Captain Marvel".to_owned(),
   year: 2019,
};

// Convert `captain_marvel` to a Bson instance:
let serialized_movie = bson::to_bson(&captain_marvel)?;
let document = serialized_movie.as_document().unwrap();

// Insert into the collection and extract the inserted_id value:
let insert_result = movies.insert_one(document.to_owned(), None).await?;
let captain_marvel_id = insert_result
   .inserted_id
   .as_object_id()
   .expect("Retrieved _id should have been of type ObjectId");
println!("Captain Marvel document ID: {:?}", captain_marvel_id);

上記のコードを実行すると、出力は次のようになりました。

Captain Marvel document ID: ObjectId(5e835f30007760020028b0ae)

Rustのネイティブデータ型を使用してデータを作成できることは素晴らしいことですが、データを構造体に逆シリアル化できることはさらに価値があると思います。これが次にお見せするものです。多くの点で、これは上記と同じプロセスですが、逆です。

以下のコードは、単一のムービードキュメントを取得し、それをBson::Document値に変換して から呼び出しますfrom_bson。これにより、BSONから式の左側にあるタイプにデシリアライズされます。これが、rustコンパイラがその情報を取得できるようにするのではなく、左側loaded_movieでタイプを指定する必要がある理由Movieです。別の方法は、呼び出しでターボフィッシュ表記を使用してfrom_bson、明示的にを呼び出すこと from_bson::<Movie>(loaded_movie)です。結局のところ、Rustの多くの場合と同様に、それはあなたの選択です。

// Retrieve Captain Marvel from the database, into a Movie struct:
// Read the document from the movies collection:
let loaded_movie = movies
   .find_one(Some(doc! { "_id":  captain_marvel_id.clone() }), None)
   .await?
   .expect("Document not found");

// Deserialize the document into a Movie instance
let loaded_movie_struct: Movie = bson::from_bson(Bson::Document(loaded_movie))?;
println!("Movie loaded from collection: {:?}", loaded_movie_struct);

そして最後に、Movie構造体のデバッグ表現を印刷したときに得たものは次のDebugとおりです(これが、上記の構造体定義から派生した理由です)。

Movie loaded from collection: Movie { id: Some(ObjectId(5e835f30007760020028b0ae)), title: "Captain Marvel", year: 2019 }

githubでTokioの完全なコード例確認できます。

東京で走りたくないとき

非同期標準

async-std代わりに使用しtokioたい場合は、幸運です!変更は簡単です。まず、デフォルトの機能を無効にして、次の機能を有効にする必要があり async-std-runtimeます。

[dependencies]
mongodb = { version = "1.0.0", default-features = false, features=["async-std-runtime"] }

rustコードに加える必要がある唯一の変更はuse async_std;、インポートに追加し、非同期メイン関数に#[async_std::main]。をタグ付けすることです。残りのコードはすべて、Tokioの例と同じである必要があります。

use async_std;

#[async_std::main]
async fn main() -> Result<(), Box<dyn Error>> {
   // Your code goes here.
}

 

githubで完全なasync-stdコード例確認できます。

同期コード

非同期フレームワークで実行したくない場合は、同期機能を有効にすることができます。あなたにはCargo.toml、ファイル、デフォルトの機能を無効にして有効にしますsync

[dependencies]
mongodb = { version = "1.0.0", default-features = false, features=["sync"] }

囲み関数がもう必要ありませんasync fn。代わりにClientで定義されている別のインターフェイスを使用するmongodb::sync必要があり、IO関数の結果を待つ必要はありません。

// Use mongodb::sync::Client, instead of mongodb::Client:
let client = mongodb::sync::Client::with_uri_str(client_uri.as_ref())?;

// .insert_one().await? becomes .insert_one()?
let insert_result = movies.insert_one(new_doc.clone(), None)?;

完全な同期コード例はgithubで確認できます。

結論

ふぅ!それはかなり大きなチュートリアルでしたね。ここで説明する操作は、何度も使用する操作になるので、慣れておくとよいでしょう。

どのような私はこのチュートリアルのコードを書いて学んだことはどのくらいの値であるbsonクレートは、あなたとMongoDBのドライバに提供-それの価値は、それは少なくともだけでなく、知ることmongodbは、データの生成と変換のためにそれを使用することがありますように、クレートAたくさんあり、それは一見豊富なライブラリです。

リンク: https://www.mongodb.com/developer/quickstart/rust-crud-tutorial/

#mongodb

What is GEEK

Buddha Community

RustアプリケーションをMongoDBクラスターに接続する
宇野  和也

宇野 和也

1638702300

RustアプリケーションをMongoDBクラスターに接続する

このクイックスタートの投稿は、RustアプリケーションをMongoDBクラスターに接続するのに役立ちます。次に、コレクションに対してCreate、Read、Update、およびDelete(CRUD)操作を実行する方法を示します。最後に、serdeを使用してMongoDBのBSONドキュメントとRust構造体の間をマッピングする方法について説明します。

シリーズツールとバージョン

このシリーズは、Rustツールチェーンの最新バージョン(v1.44 +)がインストールされており、Rust構文に慣れていることを前提としています。また、コマンドラインとお気に入りのコードエディタの使用にかなり慣れていることも前提としています。

Rustは、さまざまなタスクに適した、高性能でメモリ使用量の少ない強力なシステムプログラミング言語です。現在、データを操作するためのニッチな言語ですが、その人気は急速に高まっています。

Rustを使用していて、MongoDBを使用したい場合は、このブログシリーズから始めることができます。次の方法を紹介します。

MongoDBRustドライバーをインストールします。Rustドライバーは、 MongoDBクラスターとの通信を可能にするmongodbクレートです。

MongoDBインスタンスに接続します。

データベースでドキュメントを作成、読み取り、更新、削除(CRUD)します。

シリーズの後半のブログ投稿では、ストリームの変更トランザクション、データに対して高度なクエリを実行できる驚くべき集約パイプライン機能などについて説明します。

データベースの作成

MongoDB Atlasを使用してMongoDBクラスターをホストするため、MongoDB自体の構成方法について心配する必要はありません。

AtlasでM0クラスターを使い始めましょう 。これは永久に無料で、このブログシリーズの手順を試す最も簡単な方法です。支払いの詳細を提供する必要もありません。

新しいクラスターを作成し、サンプルデータをロードする必要があります。私のすばらしい同僚であるMaxime Beugnetが、 役立つビデオチュートリアルを作成しました が、以下の手順についても説明します。

MongoDBホームページの「無料で開始」をクリックします。

詳細を入力するか、Googleアカウントをお持ちの場合は、Googleアカウントでサインアップしてください。

利用規約に同意する

スタータークラスターを作成します。

慣れているものと同じクラウドプロバイダーを選択するか、そのままにしておきます。自分に合った地域を選んでください。

必要に応じて、クラスターの名前を変更できます。私は自分のことを「RustQuickstart」と呼んでいます。

クラスタがプロビジョニングされるまでに数分かかるため、待っている間に次のステップに進むことができます。

プロジェクトを開始する

ターミナルで、コーディングプロジェクトを保存しているディレクトリに移動し、次のコマンドを実行します。

cargo new --bin rust_quickstart

これによりrust_quickstart、ほぼ空の新しいプロジェクトを含むという新しいディレクトリが作成されます。ディレクトリでCargo.toml[dependencies]セクションを開いて変更し、次のようにします。

[dependencies]2mongodb = "1.2.0"

これで、以下を実行して依存関係をダウンロードして構築できます。

cargo run

ダウンロードおよびコンパイルされた多くの依存関係が表示されるはずです。心配しないでください。これのほとんどは、初めて実行したときにのみ発生します。最後に、すべてがうまくいけば、「He​​llo、World!」と表示されます。コンソールで。

MongoDBインスタンスをセットアップします

MongoDBクラスターは、しばらくの間セットアップされて実行されているはずです。これで、先に進んで、次のステップのためにデータベースをセットアップすることができます。

Atlas Webインターフェイスでは、画面の左下に「はじめに」という緑色のボタンが表示されます。それをクリックすると、データベースをセットアップするための手順のチェックリストが表示されます。リスト内の各項目(オプションの「サンプルデータのロード」項目を含む)をクリックすると、セットアップの手順がわかります。

ユーザーを作成する

「はじめに」の手順に従って、「任意のデータベースへの読み取りおよび書き込みアクセス権」を持つユーザーを作成します。あなたはそれにあなたの選んだユーザー名とパスワードを与えることができます-それらをメモしてください、あなたはすぐにそれらを必要とするでしょう。「安全なパスワードの自動生成」ボタンを使用して、後で接続文字列に安全に貼り付けることもできる長いランダムパスワードがあることを確認します。

IPアドレスを許可する

機密データを含むアプリをデプロイする場合は、データベースに接続する必要のあるサーバーのIPアドレスのみを許可する必要があります。[IPアドレスの追加]ボタンをクリックし、[現在のIPアドレスの追加]をクリックして、最後に[確認]をクリックします。セキュリティを強化するために、アクセスリストエントリに時間制限を設定することもできます。IPアドレスが変更される場合があるため、このチュートリアル中にMongoDBクラスターに接続できなくなった場合は、戻ってこれらの手順を繰り返してください。

MongoDBに接続する

これで、このチュートリアルの要点がわかりました。RustコードをMongoDBデータベースに接続することです。「はじめに」チェックリストの最後のステップは、「クラスターに接続する」です。「アプリケーションを接続する」を選択します。

通常、表示されるダイアログでは、[ドライバー]メニューで[Rust]を選択しますが、Rustドライバーはリリースされたばかりであるため、リストに含まれていない可能性があります。バージョンが「3.6以降」の「Python」を選択する必要があります。

手順2で[接続文字列のみ]が強調表示されていることを確認し、[コピー]ボタンを押してURLをペーストボードにコピーします(一時的にテキストファイルに保存するだけで問題ありません)。ユーザー名とパスワードを保存したのと同じ場所に貼り付けます。URLには<password> パスワードのプレースホルダーがあることに注意してください。ここにパスワードを貼り付けて、「<」および「>」文字を含むプレースホルダー全体を置き換える必要があります。

Rustプロジェクトに戻りmain.rs、内容を開いて次のように置き換えます。

use mongodb::bson::{self, doc, Bson};
use std::env;
use std::error::Error;
use tokio;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
   // Load the MongoDB connection string from an environment variable:
   let client_uri =
      env::var("MONGODB_URI").expect("You must set the MONGODB_URI environment var!");

   // A Client is needed to connect to MongoDB:
   // An extra line of code to work around a DNS issue on Windows:
   let options =
      ClientOptions::parse_with_resolver_config(&client_uri, ResolverConfig::cloudflare())
         .await?;
   let client = mongodb::Client::with_options(options)?;

   // Print the databases in our MongoDB cluster:
   println!("Databases:");
   for name in client.list_database_names(None, None).await? {
      println!("- {}", name);
   }

   Ok(())
}

これを実行するには、MONGODB_URI環境変数を上記で取得した接続文字列に設定する必要があります。プラットフォームに応じて、ターミナルウィンドウで次のいずれかを実行します。

# Unix (including MacOS):
export MONGODB_URI='mongodb+srv://yourusername:yourpasswordgoeshere@rustquickstart-123ab.mongodb.net/test?retryWrites=true&w=majority'

# Windows CMD shell:
set MONGODB_URI='mongodb+srv://yourusername:yourpasswordgoeshere@rustquickstart-123ab.mongodb.net/test?retryWrites=true&w=majority'

# Powershell:
$Env:MONGODB_URI='mongodb+srv://yourusername:yourpasswordgoeshere@rustquickstart-123ab.mongodb.net/test?retryWrites=true&w=majority'

それが済んだら、cargo runこのコードを実行できます。結果は次のようになります。

$ cargo run
   Compiling rust_quickstart v0.0.1 (/Users/judy2k/development/rust_quickstart)
   Finished dev [unoptimized + debuginfo] target(s) in 3.35s
   Running `target/debug/rust_quickstart`
Database: sample_airbnb
Database: sample_analytics
Database: sample_geospatial
Database: sample_mflix
Database: sample_supplies
Database: sample_training
Database: sample_weatherdata
Database: admin
Database: local

おめでとう!RustプログラムをMongoDBに接続し、クラスター内のデータベースを一覧表示しました。このリストが表示されない場合は、サンプルデータをクラスターに正常にロードしていない可能性があります。このコマンドを実行すると上記のリストが表示されるまで、いくつかの手順に戻る必要があります。

BSON-MongoDBがデータを理解する方法

データベースのクエリと更新を進める前に、BSONの概要とMongoDBとの関係を理解し​​ておくと便利です。BSONは、MongoDBがすべてのデータを保存するために使用するバイナリデータ形式です。BSONは、MongoDBクエリ言語と集計パイプラインで使用される形式でもあります(これらについては後で説明します)。

これはJSONに類似しており、数値、文字列、配列、オブジェクト(BSONではドキュメントと呼ばれます)など、すべて同じコアタイプを処理しますが、BSONはJSONよりも多くのタイプをサポートします。これには、日付や小数などが含まれ、MongoDBコレクション内のドキュメントを識別するために通常使用される特別なObjectIdタイプがあります。BSONはバイナリ形式であるため、人間が読める形式ではありません。通常、画面に印刷すると、JSONのように印刷されます。

BSONの動的スキーマとRustの静的型システムが一致しないため、RustでBSONを処理するのは難しい場合があります。幸い、 bsonクレートは、doc!BSONドキュメントを生成するためのマクロなど、BSONデータを処理するための便利なツールをいくつか提供し、Rust構造体とBSONデータの間でシリアル化および逆シリアル化する機能のserdeを実装します。

doc!マクロを使用してドキュメント構造を作成すると、次のようになります。

let new_doc = doc! {
   "title": "Parasite",
   "year": 2020,
   "plot": "A poor family, the Kims, con their way into becoming the servants of a rich family, the Parks. But their easy life gets complicated when their deception is threatened with exposure.",
   "released": Utc.ymd(2020, 2, 7).and_hms(0, 0, 0),
};

println!の値をnew_docコンソールに出力するために使用する場合は、次のように表示されます。

{ title: "Parasite", year: 2020, plot: "A poor family, the Kims, con their way into becoming the servants of a rich family, the Parks. But their easy life gets complicated when their deception is threatened with exposure.", released: Date("2020-02-07 00:00:00 UTC") }

(ちなみに、寄生虫は絶対に素晴らしい映画です。2020年にリリースされたため、使用するデータベースにはまだ含まれていませんが、データセットは2015年に最後に更新されました。)

上記の出力はJSONに少し似ていますが、これはBSONライブラリがDisplayトレイトを実装する方法にすぎません。データは、内部では引き続きバイナリデータとして処理されます。

ドキュメントの作成

次の例はすべて 、Atlasクラスターにロードしたsample_mflixデータセットを使用してい ます。moviesIMDBのデータベースから、1903年にリリースされた映画の全負荷の詳細を含む、と呼ばれる楽しいコレクションが含まれています。

クライアントの タイプを使用すると、クラスタ内のデータベースのリストを取得することができますが、それ以外はあまりありません。実際にデータの操作を開始するには、 クライアントまたはメソッドのいずれかを使用してデータベースを取得する必要があり ます。これは次のセクションで行います。databasedatabase_with_options

前のセクションのコードは、メモリ内にドキュメントを作成します。次に、それを映画データベースに永続化します。MongoDBコレクションで何かを行う前の最初のステップは 、データベースからCollectionオブジェクトを取得すること です。これは次のように行われます。

// Get the 'movies' collection from the 'sample_mflix' database:
let movies = client.database("sample_mflix").collection("movies");

CompassまたはAtlasの[Collections]タブで映画コレクションを閲覧した場合 、ほとんどのレコードには、doc!マクロを使用して上記で作成したドキュメントよりも多くのフィールドがあることがわかります。MongoDBはデフォルトでコレクション内にスキーマを適用しないため、これはまったく問題ありません。読みやすくするためにフィールドの数を減らしました。MongoDBコレクションへの参照を取得したら、このinsert_oneメソッドを使用して単一のドキュメントを挿入できます。

let insert_result = movies.insert_one(new_doc.clone(), None).await?;
println!("New document ID: {}", insert_result.inserted_id);

このinsert_oneメソッドは、Result<InsertOneResult> ドキュメントの挿入に関する問題を特定するために使用できるタイプを返し、MongoDBで新しいドキュメント用に生成されたIDを見つけるために使用できます。このコードをメイン関数に追加すると、実行すると次のようになります。

New document ID: ObjectId("5e835f3000415b720028b0ad")

このコードは、シングルDocumentをコレクションに挿入します。あなたが一括で複数のドキュメントを挿入したい場合、それは使用する方が効率的だ insert_manyとるIntoIteratorコレクションに挿入される書類のを。

コレクションからデータを取得する

コレクションにはParasiteという名前のドキュメントが他にないことがわかっているので、レコードを挿入したときに取得したIDの代わりに、次のコードを使用してタイトルで検索できます。

// Look up one document:
let movie = movies
   .find_one(
      doc! {
            "title": "Parasite"
      },
      None,
   ).await?
   .expect("Missing 'Parasite' document.");
println!("Movie: {}", movie);

このコードは、次のような出力になります。

Movie: { _id: ObjectId("5e835f3000415b720028b0ad"), title: "Parasite", year: 2020, plot: "A poor family, the Kims, con their way into becoming the servants of a rich family, the Parks. But their easy life gets complicated when their deception is threatened with exposure.", released: Date("2020-02-07 00:00:00 UTC") }

上記の出力と非常によく似ていますが、レコードを挿入すると、MongoDBドライバーがこのドキュメントを識別するための一意のObjectIdを生成しました。MongoDBコレクション内のすべてのドキュメントには、固有の_id値があります。一意であることが保証されている値がある場合は、自分で値を指定できます。そうしないと、この場合のように、MongoDBが値を生成します。通常は、自分で明示的に値を設定することをお勧めします。

find_oneの方法は、コレクションから単一のドキュメントを取得するのに便利ですが、多くの場合、あなたは複数のレコードを検索する必要があります。この場合、findメソッドが必要になります。このメソッドは、この呼び出しと同様のオプションを取りますが、を返しますResult<Cursor>Cursor返されたデータのリストを反復するために使用されます。

検索操作とそれに付随するフィルタードキュメントは非常に強力であり、おそらくそれらを頻繁に使用します。あなたはより多くの柔軟性を必要とする場合findfind_one提供することができ、その後、私はあなたが上のドキュメントをチェックアウトをお勧めします集約パイプライン の超パワフルで、私の意見であり、MongoDBの最も強力な機能の一つ。このシリーズで、そのトピックについて別のブログ投稿を作成します。楽しみにしています。

コレクション内のドキュメントを更新する

ドキュメントがコレクションに保存されると、さまざまな方法で更新できます。ドキュメントを別のドキュメントに完全に置き換える場合は、find_one_and_replace メソッドを使用できますが、 update_one または update_manyを使用して、ドキュメントの1つ以上の部分を更新するのが一般的 です。個別のドキュメント更新はそれぞれアトミックです。これは、ドキュメント内でデータの一貫性を保つための便利な機能です。update_manyそれ自体は不可分操作ではないことに注意してください。そのためには、バージョン4.0以降のMongoDBで利用可能な(4.2以降のシャードコレクションで利用可能な)マルチドキュメントACIDトランザクションを使用する必要が あります。Rustドライバーのバージョン1.0はまだトランザクションをサポートしていませんが、間もなくリリースされます。

MongoDBで1つのドキュメントを更新するには、2つのBSONドキュメントが必要です。1つ目は、更新するドキュメントを見つけるためのクエリについて説明してい ます。2番目 のドキュメントは、コレクション内のドキュメントに対して実行する更新操作について説明しています。寄生虫の「リリース」日は2020年でしたが、これは米国でのリリースを指していると思います。正しいリリースの年はので、ここでそれに応じてレコードを更新するためのコードだ、2019年でした。

// Update the document:
let update_result = movies.update_one(
   doc! {
      "_id": &insert_result.inserted_id,
   },
   doc! {
      "$set": { "year": 2019 }
   },
   None,
).await?;
println!("Updated {} document", update_result.modified_count);

 

上記を実行すると、「更新された1ドキュメント」が出力されます。そうでない場合は、前に挿入したムービードキュメントに何かが発生しています。多分あなたはそれを削除しましたか?更新によって年の値が正しく更新されたことを確認find_oneするために、プログラムに追加できるコマンドを次に示して、更新されたドキュメントがどのように表示されるかを確認します。

// Look up the document again to confirm it's been updated:
let movie = movies
   .find_one(
      doc! {
            "_id": &insert_result.inserted_id,
      },
      None,
   ).await?
   .expect("Missing 'Parasite' document.");
println!("Updated Movie: {}", &movie);	

これらのコードブロックを実行すると、結果は次のテキストのようになりました。その年が2020年ではなく2019年になったことをどのように示しているかをご覧ください。

Updated 1 document
Updated Movie: { _id: ObjectId("5e835f3000415b720028b0ad"), title: "Parasite", year: 2019, plot: "A poor family, the Kims, con their way into becoming the servants of a rich family, the Parks. But their easy life gets complicated when their deception is threatened with exposure.", released: Date("2020-02-07 00:00:00 UTC") }

コレクションからドキュメントを削除する

上記のセクションでは、コレクション内のドキュメントを作成、読み取り、更新する方法を学びました。プログラムを数回実行したことがあれば、映画「寄生虫」のドキュメントをかなり作成したことでしょう。これで、delete_manyメソッドを使用してそれをクリアする良い機会になりました。MongoDB rustドライバーは、ドキュメントを削除するための3つの方法を提供します。

find_one_and_delete コレクションから1つのドキュメントを削除し、削除されたドキュメントが存在する場合はそれを返します。

delete_one 提供されたフィルターに一致するドキュメントを検索し、最初に見つかったドキュメント(存在する場合)を削除します。

delete_many、ご想像のとおり、提供されたフィルターに一致するドキュメントが検索され、それらがすべて削除されます。

以下のコードでは、delete_many上記のコードをテストするときに複数のレコードを作成した可能性があるため、使用しました。フィルタは名前で映画を検索するだけで、挿入されたすべてのドキュメントに一致して削除されますが、_id値で検索すると、IDが一意であるため、1つだけが削除されます。

フィールドを常にフィルタリングまたは並べ替えている場合は、コレクションの増加に合わせてパフォーマンスを向上させるために、そのフィールドにインデックスを追加することを検討する必要があります。詳細については、MongoDBマニュアルを確認してください。

// Delete all documents for movies called "Parasite":
let delete_result = movies.delete_many(
   doc! {
      "title": "Parasite"
   },
   None,
).await?;
println!("Deleted {} documents", delete_result.deleted_count);

できたね!作成、読み取り、更新、削除の操作は、MongoDBクラスター内のデータにアクセスして管理するために何度も使用するコア操作です。このチュートリアルが提供するテイスターの後で、以下についてさらに詳しく読む価値があります。

すべての読み取り、更新、および削除操作に使用されるクエリドキュメント

MongoDBドライバーがデータにアクセスして変更するために提供するすべての操作を説明するMongoDBクレートドキュメント

bson crateとそれに付随するドキュメントで は、MongoDBから挿入または取得するためのデータを作成およびマッピングする方法について説明しています。

Serdeクレートは、Rustデータ型とBSONをbsonクレートでマッピングするためのフレームワークを提供するため、それを利用する方法を学ぶことが重要です。

serdeデータを構造体にマッピングするために使用する

すぐにはわからないかもしれないbsonクレートの機能の1つは、serdeフレームワークにBSONデータ形式を提供することです。これは、Serdeクレートを利用して、Rustデータ型とBSON型の間でマッピングし、MongoDBで永続化できることを意味します。

これがどのように役立つかの例についてtitleは、new_movieドキュメントのフィールドにアクセスする方法の次の例を参照してください( serdeなし)。

// Working with Document can be verbose:
if let Ok(title) = new_doc.get_str("title") {
   println!("title: {}", title);
} else {
   println!("no title found");
}

上記のコードの最初の行は、の値titleを取得してから、それを文字列として取得しようとします(値が異なるタイプの場合はBson::as_str戻ります None)。かなり多くのエラー処理と変換が関係しています。serdeフレームワークは、受け取る予定のドキュメントに一致するフィールドを使用して、以下のような構造体を定義する機能を提供します。

// You use `serde` to create structs which can serialize & deserialize between BSON:
#[derive(Serialize, Deserialize, Debug)]
struct Movie {
   #[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
   id: Option<bson::oid::ObjectId>,
   title: String,
   year: i32,
}

この構造体をシリアル化および逆シリアル化できることをserdeに通知するマクロSerializeDeserializeマクロの使用に注意してください。このserde 属性は、idstructフィールドをBSONにシリアル化する必要があることをserdeに通知するためにも使用されます_id。これは、MongoDBが呼び出すことを想定しているものです。パラメータはskip_serializing_if = "Option::is_none"またのオプションの値があればというserdeを伝えidているNone、それがすべてでシリアライズするべきではありません。(_id: NoneBSONをMongoDBに提供すると、IDがのドキュメントが保存NULLされますが、提供しない場合は、IDが生成されます。これは、通常、必要な動作です。)

以下のコードMovieは、キャプテンマーベル映画の構造体のインスタンスを作成します。(それは素晴らしい映画ではありませんでしたか?私はその映画が大好きでした!)構造体を作成した後、コレクションに保存する前に、BSONドキュメントに変換する必要があります。これは2つのステップで行われます。最初にbson::to_bsonBsonインスタンスを返す、を使用してBson値に変換されます。次に、それをDocument呼び出すas_documentことによって、具体的にに変換さ れます。unwrap構造体をBSONにシリアル化すると、BSONドキュメントタイプが作成されることをすでに知っているので、この結果を呼び出すのは安全 です。

プログラムがbsonDocumentインスタンスを取得したら、insert_one上記の「ドキュメントの作成」セクションで行ったのとまったく同じ方法で呼び出すことができます。

// Initialize struct to be inserted:
let captain_marvel = Movie {
   id: None,
   title: "Captain Marvel".to_owned(),
   year: 2019,
};

// Convert `captain_marvel` to a Bson instance:
let serialized_movie = bson::to_bson(&captain_marvel)?;
let document = serialized_movie.as_document().unwrap();

// Insert into the collection and extract the inserted_id value:
let insert_result = movies.insert_one(document.to_owned(), None).await?;
let captain_marvel_id = insert_result
   .inserted_id
   .as_object_id()
   .expect("Retrieved _id should have been of type ObjectId");
println!("Captain Marvel document ID: {:?}", captain_marvel_id);

上記のコードを実行すると、出力は次のようになりました。

Captain Marvel document ID: ObjectId(5e835f30007760020028b0ae)

Rustのネイティブデータ型を使用してデータを作成できることは素晴らしいことですが、データを構造体に逆シリアル化できることはさらに価値があると思います。これが次にお見せするものです。多くの点で、これは上記と同じプロセスですが、逆です。

以下のコードは、単一のムービードキュメントを取得し、それをBson::Document値に変換して から呼び出しますfrom_bson。これにより、BSONから式の左側にあるタイプにデシリアライズされます。これが、rustコンパイラがその情報を取得できるようにするのではなく、左側loaded_movieでタイプを指定する必要がある理由Movieです。別の方法は、呼び出しでターボフィッシュ表記を使用してfrom_bson、明示的にを呼び出すこと from_bson::<Movie>(loaded_movie)です。結局のところ、Rustの多くの場合と同様に、それはあなたの選択です。

// Retrieve Captain Marvel from the database, into a Movie struct:
// Read the document from the movies collection:
let loaded_movie = movies
   .find_one(Some(doc! { "_id":  captain_marvel_id.clone() }), None)
   .await?
   .expect("Document not found");

// Deserialize the document into a Movie instance
let loaded_movie_struct: Movie = bson::from_bson(Bson::Document(loaded_movie))?;
println!("Movie loaded from collection: {:?}", loaded_movie_struct);

そして最後に、Movie構造体のデバッグ表現を印刷したときに得たものは次のDebugとおりです(これが、上記の構造体定義から派生した理由です)。

Movie loaded from collection: Movie { id: Some(ObjectId(5e835f30007760020028b0ae)), title: "Captain Marvel", year: 2019 }

githubでTokioの完全なコード例確認できます。

東京で走りたくないとき

非同期標準

async-std代わりに使用しtokioたい場合は、幸運です!変更は簡単です。まず、デフォルトの機能を無効にして、次の機能を有効にする必要があり async-std-runtimeます。

[dependencies]
mongodb = { version = "1.0.0", default-features = false, features=["async-std-runtime"] }

rustコードに加える必要がある唯一の変更はuse async_std;、インポートに追加し、非同期メイン関数に#[async_std::main]。をタグ付けすることです。残りのコードはすべて、Tokioの例と同じである必要があります。

use async_std;

#[async_std::main]
async fn main() -> Result<(), Box<dyn Error>> {
   // Your code goes here.
}

 

githubで完全なasync-stdコード例確認できます。

同期コード

非同期フレームワークで実行したくない場合は、同期機能を有効にすることができます。あなたにはCargo.toml、ファイル、デフォルトの機能を無効にして有効にしますsync

[dependencies]
mongodb = { version = "1.0.0", default-features = false, features=["sync"] }

囲み関数がもう必要ありませんasync fn。代わりにClientで定義されている別のインターフェイスを使用するmongodb::sync必要があり、IO関数の結果を待つ必要はありません。

// Use mongodb::sync::Client, instead of mongodb::Client:
let client = mongodb::sync::Client::with_uri_str(client_uri.as_ref())?;

// .insert_one().await? becomes .insert_one()?
let insert_result = movies.insert_one(new_doc.clone(), None)?;

完全な同期コード例はgithubで確認できます。

結論

ふぅ!それはかなり大きなチュートリアルでしたね。ここで説明する操作は、何度も使用する操作になるので、慣れておくとよいでしょう。

どのような私はこのチュートリアルのコードを書いて学んだことはどのくらいの値であるbsonクレートは、あなたとMongoDBのドライバに提供-それの価値は、それは少なくともだけでなく、知ることmongodbは、データの生成と変換のためにそれを使用することがありますように、クレートAたくさんあり、それは一見豊富なライブラリです。

リンク: https://www.mongodb.com/developer/quickstart/rust-crud-tutorial/

#mongodb