一括操作
Overview
このガイドでは、Rust ドライバーを使用して一括操作を実行する方法を学習できます。
一括操作は、1 つ以上の名前空間に対して複数の書込み操作を実行します。 名前空間は、データベース名とコレクション名の組み合わせで、形式は <database>.<collection>
です。 Client
インスタンスで一括操作を実行するため、クライアントがアクセスするクラスター内の任意の名前空間に対して一括操作を実行できます。
一括操作を実行して、サーバーへの呼び出し回数を減らすことができます。 一括操作では、各操作のリクエストを送信する代わりに、1 つのアクション内に複数の操作を実行します。
このガイドには、次のセクションが含まれています。
サンプル データは、一括操作の例で使用されるサンプル データを提供します
一括操作タイプでは、
WriteModel
タイプを使用して一括挿入、置換、アップデート、削除操作を実行する方法について説明します戻り値の型は、
bulk_write()
メソッドの戻り値と、一括操作に関する情報にアクセスする方法を示します「動作の変更」では、
bulk_write()
メソッドのデフォルトの動作を変更する方法について説明します。混合名前空間への書き込みでは、1 回のメソッド呼び出しで複数の名前空間に対して一括操作を実行する方法について説明します
追加情報では、このガイドで言及されている型とメソッドのリソースとAPIドキュメントへのリンクを提供します
重要
一括書き込み操作を実行するには、アプリケーションが次の要件を満たしていることを確認してください。
MongoDB Server バージョン8.0以降に接続している場合
Rust ドライバー バージョン3.0以降を使用している。
サンプル データ
このガイドの例では、 db
データベースのmushrooms
コレクションに保存されている次のサンプル ドキュメントを使用します。
let docs = vec![ doc! {"name" : "portobello", "color" : "brown", "edible" : true }, doc! {"name" : "chanterelle", "color" : "yellow", "edible" : true }, doc! {"name" : "oyster", "color" : "white", "edible" : true }, doc! {"name" : "fly agaric", "color" : "red", "edible" : false }, ];
カスタム構造体 を使用してサンプル データを表すこともできます。 Mushroom
構造体を使用して同じデータをモデル化して一括操作を実行する例については、このページの「 構造体の挿入の例」を参照してください。
一括操作のタイプ
一括書き込み操作を実行するには、 WriteModel
列挙インスタンスの配列をbulk_write()
メソッドに渡します。
このセクションでは、対応するWriteModel
タイプを定義することで、次の一括書き込み操作を実行する方法を説明します。
Tip
単一のbulk_write()
メソッド呼び出しで複数のタイプの書込み操作を実行することもできます。 UpdateOneModel
とInsertOneModel
を同じbulk_write()
呼び出しに渡す例については、このガイドの「動作の変更 」の例を参照してください。
Insert
一括挿入操作を実行するには、挿入するドキュメントごとにInsertOneModel
インスタンスを作成します。 次に、モデルのリストをbulk_write()
メソッドに渡します。
次の表では、対応するビルダー メソッドを呼び出して設定できるInsertOneModel
フィールドについて説明しています。
フィールド | 説明 |
---|---|
| The namespace on which the insert is performed. Type: Namespace |
| The document to insert. Type: Document |
ドキュメントの挿入の例
この例では、次のアクションを実行します。
配列内の 2 つの
InsertOneModel
インスタンスを指定します。 各InsertOneModel
は、db.mushrooms
名前空間に挿入するドキュメントを表します。モデルの配列を
bulk_write()
メソッドに渡します。挿入されたドキュメントの数を出力します。
let mushrooms: Collection<Document> = client.database("db").collection("mushrooms"); let models = vec![ InsertOneModel::builder() .namespace(mushrooms.namespace()) .document(doc! { "name": "lion's mane", "color": "white", "edible": true }) .build(), InsertOneModel::builder() .namespace(mushrooms.namespace()) .document(doc! { "name": "angel wing", "color": "white", "edible": false }) .build(), ]; let result = client.bulk_write(models).await?; println!("Inserted documents: {}", result.inserted_count);
Inserted documents: 2
構造体を挿入した例
また、 構造体 と 構造体インスタンスをdb.mushrooms
名前空間に一括挿入して、ドキュメントをモデル化することもできます。
この例では、前述のドキュメントの挿入の例と同じ操作を実行しますが、次のMushroom
構造体型のインスタンスを挿入します。
struct Mushroom { name: String, color: String, edible: bool, }
次のコードでは、 insert_one_model()
メソッドを使用して各Mushroom
インスタンスからInsertOneModel
を構築し、両方のモデルを一括操作で挿入します。
let mushrooms: Collection<Mushroom> = client.database("db").collection("mushrooms"); let lions_mane = Mushroom { name: "lion's mane".to_string(), color: "white".to_string(), edible: true, }; let angel_wing = Mushroom { name: "angel wing".to_string(), color: "white".to_string(), edible: false, }; let lions_mane_model = mushrooms.insert_one_model(lions_mane)?; let angel_wing_model = mushrooms.insert_one_model(angel_wing)?; let result = client.bulk_write([lions_mane_model, angel_wing_model]).await?; println!("Inserted documents: {}", result.inserted_count);
Inserted documents: 2
Tip
Rust ドライバーのカスタム構造体型と直列化の詳細については、 データ モデリングと直列化に関するガイドをご覧ください。
置換
一括置換操作を実行するには、置き換えるドキュメントごとにReplaceOneModel
インスタンスを作成します。 次に、モデルのリストをbulk_write()
メソッドに渡します。
次の表では、対応するビルダー メソッドを呼び出して設定できるReplaceOneModel
フィールドについて説明しています。
フィールド | 説明 |
---|---|
| The namespace on which the operation is performed. Type: Namespace |
| The filter that matches the document you want to replace. Type: Document |
| The replacement document. Type: Document |
| (Optional) The collation to use when sorting results. To learn more about collations,
see the Collations guide. Type: Document |
| (Optional) The index to use for the operation. To learn more about
indexes, see the Indexes guide. Type: Bson |
| (Optional) Whether a new document is created if no document matches the filter. By default, this field is set to false .Type: bool |
例
この例では、次のアクションを実行します。
配列内の 2 つの
ReplaceOneModel
インスタンスを指定します。ReplaceOneModel
インスタンスには、db.mushrooms
名前空間内のきのこのドキュメントを置き換えるための指示が含まれています。モデルの配列を
bulk_write()
メソッドに渡します。変更されたドキュメントの数を出力します。
let mushrooms: Collection<Document> = client.database("db").collection("mushrooms"); let models = vec![ ReplaceOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "name": "portobello" }) .replacement(doc! { "name": "cremini", "color": "brown", "edible": true }) .build(), ReplaceOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "name": "oyster" }) .replacement(doc! { "name": "golden oyster", "color": "yellow", "edible": true }) .upsert(true) .build(), ]; let result = client.bulk_write(models).await?; println!("Modified documents: {}", result.modified_count);
Modified documents: 2
Update
一括更新操作を実行するには、実行する更新ごとにUpdateOneModel
またはUpdateManyModel
インスタンスを作成します。 次に、モデルのリストをbulk_write()
メソッドに渡します。 UpdateOneModel
はフィルターに一致するドキュメントを 1 つだけ更新し、 UpdateManyModel
はフィルターに一致するすべてのドキュメントを更新します。
次の表では、対応するビルダーUpdateOneModel
UpdateManyModel
メソッドを呼び出して設定できる フィールドと フィールドについて説明しています。
フィールド | 説明 |
---|---|
| The namespace on which the operation is performed. Type: Namespace |
| The filter that matches one or more documents you want to update. When specified in an UpdateOneModel ,
only the first matching document will be updated. When specified in an UpdateManyModel , all
matching documents will be updated.Type: Document |
| The update to perform. Type: UpdateModifications |
| (Optional) A set of filters specifying which array elements an update applies to if you are updating an
array-valued field. Type: Array |
| (Optional) The collation to use when sorting results. To learn more about collations,
see the Collations guide. Type: Document |
| (Optional) The index to use for the operation. To learn more about
indexes, see the Indexes guide. Type: Bson |
| (Optional) Whether a new document is created if no document matches the filter.
By default, this field is set to false .Type: bool |
例
この例では、次のアクションを実行します。
配列で インスタンスと
UpdateOneModel
UpdateManyModel
インスタンスを指定します。これらのモデルには、db.mushrooms
名前空間内のシノニムを表すドキュメントを更新するための指示が含まれています。モデルの配列を
bulk_write()
メソッドに渡します。変更されたドキュメントの数を出力します。
let mushrooms: Collection<Document> = client.database("db").collection("mushrooms"); let models = vec![ WriteModel::UpdateOne( UpdateOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "name": "fly agaric" }) .update(doc! { "$set": { "name": "fly amanita" } }) .upsert(true) .build(), ), WriteModel::UpdateMany( UpdateManyModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "color": "yellow" }) .update(doc! { "$set": { "color": "yellow/orange" } }) .build(), ), ]; let result = client.bulk_write(models).await?; println!("Modified documents: {}", result.modified_count);
Modified documents: 2
削除
一括削除操作を実行するには、削除操作ごとにDeleteOneModel
またはDeleteManyModel
インスタンスを作成します。 次に、モデルのリストをbulk_write()
メソッドに渡します。 DeleteOneModel
はフィルターに一致するドキュメントを 1 つだけ削除し、 DeleteManyModel
はフィルターに一致するすべてのドキュメントを削除します。
次の表では、対応するビルダーDeleteOneModel
DeleteManyModel
メソッドを呼び出して設定できる フィールドと フィールドについて説明しています。
フィールド | 説明 |
---|---|
| The namespace on which the operation is performed. Type: Namespace |
| The filter that matches one or more documents you want to delete. When specified in a DeleteOneModel ,
only the first matching document will be deleted. When specified in a DeleteManyModel , all
matching documents will be deleted.Type: Document |
| (Optional) The collation to use when sorting results. To learn more about collations,
see the Collations guide. Type: Document |
| (Optional) The index to use for the operation. To learn more about
indexes, see the Indexes guide. Type: Bson |
例
この例では、次のアクションを実行します。
配列で インスタンスと
DeleteOneModel
DeleteManyModel
インスタンスを指定します。これらのモデルには、db.mushrooms
名前空間内のシノニムを表すドキュメントを削除するための手順が含まれています。モデルの配列を
bulk_write()
メソッドに渡します。削除されたドキュメントの数を出力します。
let mushrooms: Collection<Document> = client.database("db").collection("mushrooms"); let models = vec![ WriteModel::DeleteOne( DeleteOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "color": "red" }) .build(), ), WriteModel::DeleteMany( DeleteManyModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "edible": true }) .build(), ), ]; let result = client.bulk_write(models).await?; println!("Deleted documents: {}", result.deleted_count);
Deleted documents: 4
戻り値の型
bulk_write()
メソッドは、一括操作に関する情報にアクセスできるSummaryBulkWriteResult
構造体インスタンスを返します。
SummaryBulkWriteResult
型には次のフィールドがあります。
inserted_count
: 挿入されたドキュメントの数matched_count
: 一致したドキュメントの数modified_count
: 更新されたドキュメントの数upserted_count
: アップサートされた文書の数deleted_count
: 削除されたドキュメントの数
また、 verbose_results()
メソッドを使用して、各操作に関する詳細情報を表示することもできます。 verbose_results()
メソッドは、次のフィールドを持つVerboseBulkWriteResult
構造体インスタンスを返します。
delete_results
: 成功した各削除操作の結果insert_results
: 成功した各挿入操作の結果update_results
: 成功した各更新操作の結果summary
: 各操作タイプの結果の概要
次の例では、 verbose_results()
メソッドをbulk_write()
メソッドに連結し、アップデート操作と削除操作の結果を出力します。
let models = vec![ WriteModel::DeleteOne( DeleteOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "name": "oyster" }) .build(), ), WriteModel::UpdateOne( UpdateOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "name": "chanterelle" }) .update(doc! { "$set": { "season": ["July", "August", "September"] } }) .build(), ), ]; let result = client.bulk_write(models).verbose_results().await?; println!( "Update results: {:?}\nDelete results: {:?}\n", result.update_results, result.delete_results );
Update results: {1: UpdateResult { matched_count: 1, modified_count: 1, upserted_id: None }} Delete results: {0: DeleteResult { deleted_count: 1 }}
動作の変更
BulkWriteOptions
フィールド値を設定することで、 bulk_write()
メソッドの動作を変更できます。 これらの構造体フィールドを設定するには、フィールドに対応するメソッドをbulk_write()
メソッドに連鎖させます。
BulkWriteOptions
構造体には次のフィールドが含まれています。
フィールド | 説明 | デフォルト値 |
---|---|---|
| Whether the operations run in the order in which they were specified. When set to true , one failed operation prevents subsequent operations from running.When set to false , the server continues to attempt write operations if one fails.Type: bool |
|
| Whether document-level validation is bypassed. Type: bool |
|
| An arbitrary comment to help trace the operation through the database profiler, currentOp,
and logs. Type: Bson |
|
| A map of parameter names and values to apply to all operations within the bulk write.
Values must be constant or closed expressions that do not reference document fields. Type: Document |
|
| The write concern to use for this bulk operation. Type: WriteConcern | 名前空間の書込み保証 (write concern) を継承します |
例
この例では、 mushrooms
コレクションに対してアップデート操作と挿入操作を実行しようとしています。 次のコードでは、 ordered()
メソッドをbulk_write()
メソッドに連結して、 ordered
フィールドをfalse
に設定します。
let mushrooms: Collection<Document> = client.database("db").collection("mushrooms"); let models = vec![ WriteModel::UpdateOne(UpdateOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "name": "portobello" }) .update(doc! { "$set": { "_id": 123 } }) .upsert(true) .build()), WriteModel::InsertOne(InsertOneModel::builder() .namespace(mushrooms.namespace()) .document(doc! { "name": "reishi", "color": "red/brown", "edible": true }) .build()), ]; let result = client.bulk_write(models).ordered(false).await?; println!( "Inserted documents: {}\nDeleted documents: {}", result.inserted_count, result.deleted_count );
Error: Error { kind: BulkWrite(BulkWriteError { write_concern_errors: [], write_errors: {0: WriteError { code: 66, code_name: None, message: "Plan executor error during update :: caused by :: Performing an update on the path '_id' would modify the immutable field '_id'", details: None }}, partial_result: Some(Summary(SummaryBulkWriteResult { inserted_count: 1, matched_count: 0, modified_count: 0, upserted_count: 0, deleted_count: 0 })) }), labels: ... }
_id
フィールドは不変であり、更新操作では変更できません。 UpdateOneModel
にはこのフィールドをアップデートするための指示が含まれているため、一括操作はBulkWriteError
を返し、挿入操作のみを実行します。 ordered
フィールドをtrue
に設定すると、ドライバーは失敗した更新操作後に後続の操作を試行せず、ドキュメントを挿入しません。
混合名前空間への書込み
このページの前述の例では、 db.mushrooms
名前空間に対して一括操作を実行しています。 ただし、1 回のメソッド呼び出しで複数の名前空間に対して一括書き込みを実行できます。
次の例では、 ingredients.sweet
名前空間に 1 つのドキュメントを挿入し、 meals.dessert
名前空間に 2 つのドキュメントを挿入します。
let sweet: Collection<Document> = client .database("ingredients") .collection("sweet"); let dessert: Collection<Document> = client .database("meals") .collection("dessert"); let models = vec![ InsertOneModel::builder() .namespace(sweet.namespace()) .document(doc! { "name": "brown sugar", "price": 3.99 }) .build(), InsertOneModel::builder() .namespace(dessert.namespace()) .document(doc! { "name": "banana bread", "cook_time": 75 }) .build(), ]; let result = client.bulk_write(models).await?; println!("Inserted documents: {}", result.inserted_count);
Inserted documents: 2
詳細情報
一括操作の詳細については、サーバー マニュアルの「一括書込み操作」を参照してください。