翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
Java を使用した Amazon DocumentDB での CRUD オペレーションの実行
このセクションでは、MongoDB Java ドライバーを使用して Amazon DocumentDB で CRUD (作成、読み取り、更新、削除) オペレーションを実行する方法について説明します。
トピック
DocumentDB コレクションでのドキュメントの作成と挿入
Amazon DocumentDB にドキュメントを挿入すると、コレクションに新しいデータを追加できます。挿入を実行するには、ニーズと使用しているデータの量に応じて、いくつかの方法があります。個々のドキュメントをコレクションに挿入する最も基本的な方法は ですinsertOne()
。一度に複数のドキュメントを挿入するには、 insertMany()
メソッドを使用できます。これにより、1 回のオペレーションでドキュメントの配列を追加できます。DocumentDB コレクションに多くのドキュメントを挿入するもう 1 つの方法は、 ですbulkWrite()
。このガイドでは、DocumentDB コレクションでドキュメントを作成するためのこれらのすべての方法について説明します。
insertOne()
まず、個々のドキュメントを Amazon DocumentDBB コレクションに挿入する方法を見てみましょう。単一のドキュメントを挿入するには、 insertOne()
メソッドを使用します。このメソッドは、挿入のために BsonDocumentInsertOneResult
Document article = new Document() .append("restaurantId", "REST-21G145") .append("name", "Future-proofed Intelligent Bronze Hat") .append("cuisine", "International") .append("rating", new Document() .append("average", 1.8) .append("totalReviews", 267)) .append("features", Arrays.asList("Outdoor Seating", "Live Music")); try { InsertOneResult result = collection.insertOne(article); System.out.println("Inserted document with the following id: " + result.getInsertedId()); } catch (MongoWriteException e) { // Handle duplicate key or other write errors System.err.println("Failed to insert document: " + e.getMessage()); throw e; } catch (MongoException e) { // Handle other MongoDB errors System.err.println("MongoDB error: " + e.getMessage()); throw e; }
を使用する場合はinsertOne()
、適切なエラー処理を必ず含めてください。たとえば、上記のコードでは、restaurantId
「」には一意のインデックスがあるため、このコードを再度実行すると、次の が生成されますMongoWriteException
。
Failed to insert document: Write operation error on server docdbCluster.docdb.amazonaws.com:27017.
Write error: WriteError{code=11000, message='E11000 duplicate key error collection: Restaurants index: restaurantId_1', details={}}.
insertMany()
コレクションに多くのドキュメントを挿入する主な方法は、 insertMany() と ですbulkWrite()
。
insertMany()
メソッドは、1 回のオペレーションで複数のドキュメントを挿入する最も簡単な方法です。ドキュメントのリストを受け入れ、コレクションに挿入します。この方法は、互いに独立しており、特別な処理や混合操作を必要としない新しいドキュメントのバッチを挿入する場合に最適です。次のコードは、ファイルから JSON ドキュメントを読み取ってコレクションに挿入する方法を示しています。insertMany()
関数は、挿入されたすべてのドキュメントの IDsを取得するために使用できる InsertManyResult
InsertManyResult
オブジェクトを返します。
// Read JSON file content String content = new String(Files.readAllBytes(Paths.get(jsonFileName))); JSONArray jsonArray = new JSONArray(content); // Convert JSON articles to Documents List < Document > restaurants = new ArrayList < > (); for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); Document doc = Document.parse(jsonObject.toString()); restaurants.add(doc); } //insert documents in collection InsertManyResult result = collection.insertMany(restaurants); System.out.println("Count of inserted documents: " + result.getInsertedIds().size());
bulkWrite()
メソッドを使用すると、複数の書き込みオペレーション (挿入、更新、削除) を 1 つのバッチで実行できます。は、一部のドキュメントを挿入して他のドキュメントを更新するなど、1 つのバッチでさまざまなタイプのオペレーションを実行bulkWrite()
する必要がある場合に使用できます。 は、順序付きと順序なしの 2 種類のバッチ書き込みbulkWrite()
をサポートしています。
順序付けられたオペレーション — (デフォルト) Amazon DocumentDB は書き込みオペレーションを順番に処理し、最初に発生したエラーで停止します。これは、後のオペレーションが以前のオペレーションに依存する場合など、オペレーションの順序が重要な場合に役立ちます。ただし、順序付けられたオペレーションは、通常、順序付けられていないオペレーションよりも遅くなります。順序付けられたオペレーションでは、バッチが最初のエラーで停止し、一部のオペレーションが未処理のままになる可能性があるケースに対処する必要があります。
順序付けされていないオペレーション — Amazon DocumentDB が挿入をデータベース内の 1 回の実行として処理できるようにします。1 つのドキュメントでエラーが発生した場合、オペレーションは残りのドキュメントで続行されます。これは、大量のデータを挿入していて、キーの重複が原因で一部のドキュメントが失敗する可能性のあるデータ移行や一括インポートなど、一部の障害を許容できる場合に特に便利です。順序付けされていないオペレーションでは、一部のオペレーションが成功し、他のオペレーションが失敗する部分的な成功シナリオに対処する必要があります。
bulkWrite()
メソッドを使用する場合、必須のクラスがいくつかあります。まず、 WriteModel
InsertOneModel
UpdateManyModel
UpdateOneModel
DeleteOneModel
DeleteManyModel
BulkWriteOptions
BulkWriteResult
エラー処理では、 MongoBulkWriteException
BulkWriteError
bulkWrite()
メソッド呼び出しの実行内で、ドキュメントのリストを挿入し、1 つのドキュメントを更新および削除する例を示しています。このコードは、 BulkWriteOptions
BulkWriteResult
bulkWrite()
オペレーションの適切なエラー処理も示します。
List < WriteModel < Document >> bulkOperations = new ArrayList < > (); // get list of 10 documents representing 10 restaurants List < Document > restaurantsToInsert = getSampleData(); for (Document doc: restaurantsToInsert) { bulkOperations.add(new InsertOneModel < > (doc)); } // Update operation bulkOperations.add(new UpdateOneModel < > ( new Document("restaurantId", "REST-Y2E9H5"), new Document("", new Document("stats.likes", 20)) .append("", new Document("rating.average", 4.5)))); // Delete operation bulkOperations.add(new DeleteOneModel < > (new Document("restaurantId", "REST-D2L431"))); // Perform bulkWrite operation try { BulkWriteOptions options = new BulkWriteOptions() .ordered(false); // Allow unordered inserts BulkWriteResult result = collection.bulkWrite(bulkOperations, options); System.out.println("Inserted: " + result.getInsertedCount()); System.out.println("Updated: " + result.getModifiedCount()); System.out.println("Deleted: " + result.getDeletedCount()); } catch (MongoBulkWriteException e) { System.err.println("Bulk write error occurred: " + e.getMessage()); // Log individual write errors for (BulkWriteError error: e.getWriteErrors()) { System.err.printf("Error at index %d: %s (Code: %d)%n", error.getIndex(), error.getMessage(), error.getCode()); // Log the problematic document Document errorDoc = new Document(error.getDetails()); if (errorDoc != null) { System.err.println("Problematic document: " + errorDoc); } } } catch (Exception e) { System.err.println("Error during bulkWrite: " + e.getMessage()); }
再試行可能な書き込み
MongoDB とは異なり、Amazon DocumentDB は再試行可能な書き込みをサポートしていません。そのため、特にネットワークの問題や一時的なサービス利用不可を処理するために、アプリケーションにカスタム再試行ロジックを実装する必要があります。適切に実装された再試行戦略では、通常、再試行間の遅延を増やし、再試行の合計数を制限します。エラー処理を使用して再試行ロジックを構築するコードサンプルについては、再試行ロジックによるエラー処理以下を参照してください。
DocumentDB コレクションからのデータの読み取りと取得
Amazon DocumentDB でのドキュメントのクエリは、データを正確に取得して操作できるいくつかの主要なコンポーネントを中心に展開されます。find()
find()
メソッドに加えて、 Filters
FindIterable
Filters
クラスは、クエリフィルターを構築するための流暢な API を提供する MongoDB Java ドライバーのユーティリティクラスです。このクラスは、さまざまなクエリ条件を表すBson
オブジェクトのインスタンスを作成する静的ファクトリメソッドを提供します。最も一般的に使用される方法には、等価比較eq()
の場合は gt()
、、lt()
、gte()
、数値比較lte()
の場合は 、複数の条件を組み合わせるand()
or()
場合は 、配列メンバーシップテストin()
nin()
の場合は 、パターンマッチングregex()
の場合は が含まれます。クラスは、タイプセーフであるように設計されており、raw ドキュメントベースのクエリと比較してコンパイル時のチェックに優れているため、Java アプリケーションで DocumentDB クエリを構築するための推奨アプローチです。エラー処理は堅牢で、無効なフィルター構造には明確な例外がスローされます。
FindIterable
は、 find()
メソッドの結果を処理するように設計された特殊なインターフェイスです。クエリ実行を改良および制御するための豊富なメソッドのセットを提供し、メソッド連鎖のための流暢な API を提供します。インターフェイスには、返されるドキュメント数の制限limit()
、skip()
ページ分割、結果のsort()
順序付け、特定のフィールドの選択、インデックスの選択などprojection()
、必須hint()
のクエリ変更方法が含まれています。のバッチ、スキップ、制限オペレーションFindIterable
は、データベースからドキュメントを取得して処理する方法を制御するのに役立つ重要なページ分割およびデータ管理ツールです。
バッチ処理 (batchSize
) は、1 回のネットワークラウンドトリップで DocumentDB がクライアントに返すドキュメントの数を制御します。バッチサイズを設定すると、DocumentDB は一致するすべてのドキュメントを一度に返すのではなく、指定されたバッチサイズのグループで返します。
Skip を使用すると、結果の開始点をオフセットできます。基本的には、一致を返す前に、指定した数のドキュメントをスキップするように DocumentDB に指示します。たとえば、 skip(20)
は一致する最初の 20 のドキュメントをバイパスします。これは、後続の結果ページを取得するページ分割シナリオで一般的に使用されます。
制限は、クエリから返すことができるドキュメントの総数を制限します。を指定するとlimit(n)
、DocumentDB は、データベースにより多くの一致がある場合でも、「n」ドキュメントを返した後でドキュメントの返しを停止します。
FindIterable
は、Amazon DocumentDB からドキュメントを取得するときに、イテレーターパターンとカーソルパターンの両方をサポートします。イテレーターFindIterable
として を使用する利点は、ドキュメントの遅延ロードを許可し、アプリケーションから要求された場合にのみドキュメントを取得することです。イテレーターを使用するもう 1 つの利点は、クラスターへの接続を維持する責任がないため、接続を明示的に閉じる必要がないことです。
FindIterable
は、Amazon DocumentDB クエリを操作するときにカーソルパターンを使用MongoCursor
MongoCursor
は、データベースオペレーションとリソース管理を制御する MongoDB Java ドライバー固有の実装です。AutoCloseable
インターフェイスを実装しているため、try-with-resources ブロックによる明示的なリソース管理が可能になります。これは、データベース接続を適切に閉じ、サーバーリソースを解放するために不可欠です。デフォルトでは、カーソルは 10 分でタイムアウトし、DocumentDB はこのタイムアウト動作を変更するオプションを提供しません。バッチ処理されたデータを使用する場合は、カーソルがタイムアウトする前に、必ず次のデータのバッチを取得してください。を使用する際の 1 つの重要な考慮事項MongoCursor
は、リソースリークを防ぐために明示的な閉鎖が必要であることです。
このセクションでは、、find()
、Filters
および の例をいくつか示しますFindIterable
。
次のコード例は、 find()
を使用して、restaurantId」フィールドを使用して単一のドキュメントを取得する方法を示しています。
Document filter = new Document("restaurantId", "REST-21G145"); Document result = collection.find(filter).first();
を使用するとコンパイル時のエラーチェックFilters
が向上しますが、Java ドライバーでは find()
メソッドで直接Bson
フィルターを指定することもできます。次のコード例は、Bson
ドキュメントを に渡しますfind()
。
result = collection.find(new Document("$and", Arrays.asList( new Document("rating.totalReviews", new Document("$gt", 1000)), new Document("priceRange", "$$"))))
次のコード例は、 で Filters
クラスを使用するいくつかの例を示していますfind()
。
FindIterable < Document > results; // Exact match results = collection.find(Filters.eq("name", "Thai Curry Palace")); // Not equal results = collection.find(Filters.ne("cuisine", "Thai")); // find an element in an array results = collection.find(Filters.in("features", Arrays.asList("Private Dining"))); // Greater than results = collection.find(Filters.gt("rating.average", 3.5)); // Between (inclusive) results = collection.find(Filters.and( Filters.gte("rating.totalReviews", 100), Filters.lte("rating.totalReviews", 200))); // AND results = collection.find(Filters.and( Filters.eq("cuisine", "Thai"), Filters.gt("rating.average", 4.5))); // OR results = collection.find(Filters.or( Filters.eq("cuisine", "Thai"), Filters.eq("cuisine", "American"))); // All document where the Field exists results = collection.find(Filters.exists("michelin")); // Regex results = collection.find(Filters.regex("name", Pattern.compile("Curry", Pattern.CASE_INSENSITIVE))); // Find all document where the array contain the list of value regardless of its order results = collection.find(Filters.all("features", Arrays.asList("Private Dining", "Parking"))); // Array size results = collection.find(Filters.size("features", 4));
次の例は、 FindIterable
オブジェクトbatchSize()
に対する sort()
、、limit()
、および skip()
のオペレーションを連鎖する方法を示しています。これらのオペレーションがどのように提供されるかの順序は、クエリのパフォーマンスに影響します。ベストプラクティスとして、これらのオペレーションの順序は sort()
、projection()
、skip()
、limit()
および である必要がありますbatchSize()
。
FindIterable < Document > results = collection.find(Filters.gt("rating.totalReviews", 1000)) // Sorting .sort(Sorts.orderBy( Sorts.descending("address.city"), Sorts.ascending("cuisine"))) // Field selection .projection(Projections.fields( Projections.include("name", "cuisine", "priceRange"), Projections.excludeId())) // Pagination .skip(20) .limit(10) .batchSize(2);
次のコード例は、 でのイテレーターの作成を示していますFindIterable
。Java の forEach
コンストラクトを使用して結果セットを横断します。
collection.find(Filters.eq("cuisine", "American")).forEach(doc -> System.out.println(doc.toJson()));
最後のfind()
コード例では、 を使用してcursor()
ドキュメントを取得する方法を示しています。試行ブロックにカーソルが作成され、コードが試行ブロックを終了するとカーソルが閉じられます。
try (MongoCursor < Document > cursor = collection.find(Filters.eq("cuisine", "American")) .batchSize(25) .cursor()) { while (cursor.hasNext()) { Document doc = cursor.next(); System.out.println(doc.toJson()); } } // Cursor automatically closed
DocumentDB コレクション内の既存のドキュメントの更新
Amazon DocumentDB は、既存のドキュメントを変更し、存在しないときに新しいドキュメントを挿入するための柔軟で強力なメカニズムを提供します。MongoDB Java ドライバーには、1 つのドキュメントの更新、updateMany()
複数のドキュメントの更新、replaceOne()
完全なドキュメント置換updateOne()
の複数の更新方法が用意されています。これら 3 つのメソッドに加えて、、UpdateOptions
UpdateResult
Updates
MongoDB Java ドライバーの Updates
クラスは、更新演算子を作成するための静的ファクトリメソッドを提供するユーティリティクラスです。これは、タイプセーフで読み取り可能な方法で更新オペレーションを構築するためのプライマリビルダーとして機能します。set()
、、 などの基本的な方法でinc()
はunset()
、ドキュメントを直接変更できます。このクラスの能力は、複数の更新オペレーションをアトミックに実行できる Updates.combine()
メソッドを使用して複数のオペレーションを組み合わせると明らかになり、データの整合性が確保されます。
UpdateOptions
は、ドキュメント更新オペレーションに不可欠なカスタマイズ機能を提供する MongoDB の Java ドライバーの強力な設定クラスです。このクラスの 2 つの重要な点は、更新オペレーションのアップサートフィルターと配列フィルターのサポートを提供することです。を介して有効になっているアップサート機能を使用するとupsert(true)
、更新オペレーション中に一致するドキュメントが見つからなかった場合に、新しいドキュメントを作成できます。を通じてarrayFilters()
、更新オペレーションは特定の基準を満たす配列要素を正確に更新できます。
UpdateResult
MongoDB の Java ドライバーでは、更新オペレーションの結果を詳述するフィードバックメカニズムが提供されます。このクラスは、更新基準に一致するドキュメントの数 (matchedCount
)、実際に変更されたドキュメントの数 ()、およびアップサートされたドキュメントに関する情報 (modifiedCount
) の 3 つの主要なメトリクスをカプセル化しますupsertedId
。これらのメトリクスを理解することは、適切なエラー処理、更新オペレーションの検証、アプリケーションのデータ整合性の維持に不可欠です。
1 つのドキュメントを更新して置き換える
DocumentDB では、updateOne() メソッドを使用して 1 つのドキュメントを更新できます。このメソッドは、通常は Filters
クラスによって提供されるフィルターパラメータを使用して、更新するドキュメントを識別し、どのフィールド (複数可) を更新するかを決定する Updat
e パラメータと、更新のさまざまなオプションを設定するオプションのUpdateOptions
パラメータを使用します。updateOne()
メソッドを使用すると、選択基準に一致する最初のドキュメントのみが更新されます。次のコード例では、1 つのドキュメントの 1 つのフィールドを更新します。
collection.updateOne(Filters.eq("restaurantId", "REST-Y2E9H5"), Updates.set("name", "Amazing Japanese sushi"));
1 つのドキュメント内の複数のフィールドを更新するには、次の例Update.combine()
に示すように、 updateOne()
で を使用します。この例では、ドキュメント内の配列に項目を追加する方法も示します。
List<Bson> updates = new ArrayList<>(); // Basic field updates updates.add(Updates.set("name", "Shanghai Best")); // Array operations updates.add(Updates.addEachToSet("features", Arrays.asList("Live Music"))); // Counter updates updates.add(Updates.inc("rating.totalReviews", 10)); // Combine all updates Bson combinedUpdates = Updates.combine(updates); // Execute automic update with one call collection.updateOne(Filters.eq("restaurantId","REST-1J83NH"), combinedUpdates);
次のコード例は、データベース内のドキュメントを更新する方法を示しています。指定されたドキュメントが存在しない場合、オペレーションは自動的に新しいドキュメントとして挿入します。このコードは、 UpdateResult
オブジェクトを介して利用可能なメトリクスの使用方法も示します。
Bson filter = Filters.eq("restaurantId", "REST-0Y9GL0"); Bson update = Updates.set("cuisine", "Indian"); // Upsert operation UpdateOptions options = new UpdateOptions().upsert(true); UpdateResult result = collection.updateOne(filter, update, options); if (result.getUpsertedId() != null) { System.out.println("Inserted document with _id: " + result.getUpsertedId()); } else { System.out.println("Updated " + result.getModifiedCount() + " document(s)"); }
次のコード例は、個々のフィールドを更新するのではなく、 replaceOne()
メソッドを使用して既存のドキュメントを新しいドキュメントと完全に置き換える方法を示しています。replaceOne()
メソッドはドキュメント全体を上書きし、元の _id
フィールドのみを保持します。複数のドキュメントがフィルター条件に一致する場合、最初に検出されたドキュメントのみが置き換えられます。
Document newDocument = new Document() .append("restaurantId", "REST-0Y9GL0") .append("name", "Bhiryani Adda") .append("cuisine", "Indian") .append("rating", new Document() .append("average", 4.8) .append("totalReviews", 267)) .append("features", Arrays.asList("Outdoor Seating", "Live Music")); UpdateResult result = collection.replaceOne( Filters.eq("restaurantId", "REST-0Y9GL0"), newDocument); System.out.printf("Modified %d document%n", result.getModifiedCount());
複数のドキュメントを更新する
コレクション内の複数のドキュメントを同時に更新する方法は 2 つあります。updateMany()
メソッドを使用するか、 bulkWrite()
メソッドUpdateManyModel
updateMany()
メソッドは、フィルターパラメータを使用して更新するドキュメントを選択し、Update
パラメータを使用して更新するフィールドを識別し、オプションのUpdateOptions
パラメータを使用して更新オプションを指定します。
次のコード例は、 updateMany()
メソッドの使用方法を示しています。
Bson filter = Filters.and( Filters.in("features", Arrays.asList("Private Dining")), Filters.eq("cuisine", "Thai")); UpdateResult result1 = collection.updateMany(filter, Updates.set("priceRange", "$$$"));
次のコード例は、同じ更新を使用する bulkWrite()
メソッドを示しています。
BulkWriteOptions options = new BulkWriteOptions().ordered(false); List < WriteModel < Document >> updates = new ArrayList < > (); Bson filter = Filters.and( Filters.in("features", Arrays.asList("Private Dining")), Filters.eq("cuisine", "Indian")); Bson updateField = Updates.set("priceRange", "$$$"); updates.add(new UpdateManyModel < > (filter, updateField)); BulkWriteResult result = collection.bulkWrite(updates, options); System.out.printf("Modified %d document%n", result.getModifiedCount());
DocumentDB コレクションからのドキュメントの削除
MongoDB Java ドライバーはdeleteOne()
、1 つのドキュメントを削除したり、特定の条件に一致する複数のドキュメントを削除deleteMany()
したりできます。更新と同様に、削除オペレーションは bulkWrite()
メソッドでも使用できます。deleteOne()
と の両方が、削除されたドキュメントの数など、オペレーションの結果に関する情報を提供するDeleteResult
deleteMany()
を返します。deleteMany()
を使用して複数のドキュメントを削除する例を次に示します。
Bson filter = Filters.and( Filters.eq("cuisine", "Thai"), Filters.lt("rating.totalReviews", 50)); DeleteResult result = collection.deleteMany(filter); System.out.printf("Deleted %d document%n", result.getDeletedCount());
再試行ロジックによるエラー処理
Amazon DocumentDB の堅牢なエラー処理戦略では、エラーを再試行可能 (ネットワークタイムアウト、接続の問題など) と再試行不可能 (認証の失敗、無効なクエリなど) に分類する必要があります。再試行する必要があるエラーによるオペレーションの失敗の場合、各再試行と最大再試行回数の間に時間遅延を実装する必要があります。CRUD オペレーションは、 MongoException
int MAX_RETRIES = 3; int INITIAL_DELAY_MS = 1000; int retryCount = 0; while (true) { try { crud_operation(); //perform crud that will throw MongoException or one of its subclass break; } catch (MongoException e) { if (retryCount < MAX_RETRIES) { retryCount++; long delayMs = INITIAL_DELAY_MS * (long) Math.pow(2, retryCount - 1); try { TimeUnit.MILLISECONDS.sleep(delayMs); } catch (InterruptedException t) { Thread.currentThread().interrupt(); throw new RuntimeException("Retry interrupted", t); } continue; } else throw new RuntimeException("Crud operation failed", e); } }