Java を使用した Amazon DocumentDB でのインデックス管理 - Amazon DocumentDB

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

Java を使用した Amazon DocumentDB でのインデックス管理

インデックスを使用すると、Amazon DocumentDB コレクションからデータを効率的に取得できます。インデックスがない場合、DocumentDB はコレクション内のすべてのドキュメントをスキャンして、特定のクエリを満たす結果を返す必要があります。このトピックでは、MongoDB Java ドライバーを使用してインデックスを作成、削除、および一覧表示する方法について説明します。また、クエリで特定のインデックスが使用されているかどうかを判断する方法と、特定のインデックスを使用するように Amazon DocumentDB にヒントを与える方法について説明します。

Amazon DocumentDB は、多くのタイプのインデックスをサポートしています。サポートされているすべてのインデックスの包括的な概要については、このブログ記事を参照してください。

Java を使用したインデックスの作成

MongoDB Java ドライバーを使用して Amazon DocumentDB でインデックスを作成するメカニズムには、 とrunCommand()、単一のインデックスの createIndex()メソッドまたは複数のインデックスの createIndexes()メソッドの 2 つがあります。 MongoDB createIndex() および createIndexes()メソッドを使用する理由の 1 つは、インデックス作成に関連する特定のエラーをキャッチすることで、より良いエラー処理を構築できることです。これらのメソッドを で使用するもう 1 つの理由はrunCommand()、MongDB Java ドライバーがインデックスの作成と操作のための豊富なサポートクラスを提供することです。これらのサポートクラスは、 createIndex() または createIndexes()メソッドを使用している場合にのみ使用できることに注意してください。3 つのサポートクラスがあります。

  • Indexes — このクラスは、さまざまなタイプのインデックスを作成するための静的ファクトリメソッドを提供するユーティリティクラスとして機能します。これにより、複雑なインデックス定義を作成するプロセスが簡素化され、一般的に他のインデックス関連クラスと組み合わせて使用されます。

  • IndexModel — これは、インデックスキー定義とそのオプションの両方をカプセル化する基本的なクラスです。これは、インデックスを作成する内容 (キー) とインデックスを作成する方法 (オプション) を組み合わせた完全なインデックス仕様を表します。このクラスは、createIndexes()メソッドに渡すことができるインデックス仕様のコレクションを定義できるため、複数のインデックスを同時に作成する場合に特に便利です。

  • IndexOptions — これは、インデックスの動作をカスタマイズするための豊富なメソッドのセットを提供する包括的な設定クラスです。これには、一意のインデックス、スパースインデックス、有効期限 (TTL)、部分フィルター式の設定が含まれます。メソッドチェーンを使用すると、バックグラウンドインデックスの構築や一意の制約など、複数のオプションを設定できます。

単一のインデックスを作成する

この例では、バックグラウンドで createIndex() メソッドを使用して単一のインデックスを作成する方法を示します。背景インデックスとフォアグラウンドインデックスの作成については、「」を参照してくださいインデックスビルドのタイプ。次のコード例ではIndexOptions、 を使用して、バックグラウンドで「unique_restaurantId_idx」という名前の一意のインデックスを作成します。その後、このIndexOptionsオブジェクトは createIndex()メソッドに渡されます。

collection.createIndex( Indexes.ascending("restaurantId"), new IndexOptions() .unique(true) .name("unique_restaurantId_idx") .background(true));

複数のインデックスを作成する

この例では、 createIndexes()メソッドを使用して複数のインデックスを作成します。まず、 IndexModel オブジェクトを使用して各インデックスのオプションを構築し、次にIndexModelオブジェクトのリストを createIndexes()メソッドに渡します。次のコード例は、 Indexesユーティリティクラスを使用して複合インデックスを作成する方法を示しています。このクラスは、昇順または降順のソート順序を使用してインデックスを作成するかどうかを指定するためにも使用されます。複数のインデックスを作成した後、 listIndexes()メソッドを呼び出してインデックスの作成を検証します。

// Single Field Index on cuisine IndexModel singleIndex = new IndexModel( Indexes.ascending("cuisine"), new IndexOptions().name("cuisine_idx")); // Compound Index IndexModel compoundIndex = new IndexModel( Indexes.compoundIndex( Indexes.ascending("address.state"), Indexes.ascending("priceRange")), new IndexOptions().name("location_price_idx")); // Build a list of IndexModel for the indexes List < IndexModel > indexes = Arrays.asList( singleIndex, compoundIndex ); collection.createIndexes(indexes); // Verify created indexes collection.listIndexes().forEach(index - > System.out.println("Created index: " + index.toJson()));

スパースインデックスと部分インデックスを作成する

この例では、インデックスのタイプIndexModelごとに を作成して、スパースインデックスと部分インデックスを作成します。

// Sparse Index Model, this will identify only those documents that have a // michelin star rating IndexModel sparseIndex = new IndexModel( Indexes.ascending("michelin.star"), new IndexOptions() .name("michelin_sparse_idx") .sparse(true)); // Partial Index Model where the restaurant is active and has a rating of 4 and above IndexModel partialIndex = new IndexModel( Indexes.ascending("rating.average"), new IndexOptions() .name("high_rated_active_idx") .partialFilterExpression( Filters.and( Filters.eq("isActive", true), Filters.gte("rating.average", 4.0))));

テキストインデックスを作成する

この例では、テキストインデックスを作成する方法を示します。コレクションでは 1 つのテキストインデックスのみが許可されますが、1 つのテキストインデックスを複数のフィールドをカバーする複合インデックスにすることができます。テキストインデックスで複数のフィールドを使用する場合、インデックス内の各フィールドに重みを割り当てることもできます。配列フィールドのテキストインデックスは Amazon DocumentDB ではサポートされていません。複合テキストインデックスでは最大 30 個のフィールドを使用できますが、重みを割り当てることができるフィールドは 3 つだけです。

IndexModel textIndex = new IndexModel( new Document() .append("name", "text") .append("description", "text") .append("cuisine", "text"), new IndexOptions() .name("restaurant_text_idx") .weights(new Document() .append("name", 10) // Restaurant name gets highest weight .append("description", 5) // Description get medium weight .append("cuisine", 2) // Cuisine type gets low weight )); collection.createIndex(textIndex.getKeys(), textIndex.getOptions());

を使用してインデックスを作成する runCommand()

Amazon DocumentDB は、インデックスの作成にかかる時間を短縮するために、並列インデックスの作成をサポートしています。並列インデックス作成は、複数の同時ワーカーを使用します。インデックスの作成に使用されるデフォルトのワーカーは 2 です。このブログ記事では、並列インデックス作成について詳しく説明します。現在、MongDB Java ドライバーは、 createIndex()または を使用しているときにワーカーオプションの指定をサポートしていないためcreateIndexes()、ワーカーを指定する唯一の方法は を使用することですrunCommand。次のコード例は、 runCommandを使用して、ワーカーを 4 つに増やすインデックスを作成する方法を示しています。

Document command = new Document("createIndexes", "Restaurants") .append("indexes", Arrays.asList( new Document("key", new Document("name", 1)) .append("name", "restaurant_name_idx") .append("workers", 4) // Specify number of workers )); Document commendResult = connectedDB.runCommand(command);

インデックスの削除

MongoDB Java ドライバーは、さまざまなシナリオや好みに応じて、インデックスを削除する複数の方法を提供します。インデックスは、名前、キー仕様、またはすべてのインデックスを一度に削除できます。メソッドdropIndex()と は、コレクションオブジェクトで呼び出してインデックスを削除dropIndexes()できます。インデックスを名前で削除するときは、特に複合インデックスまたは自動生成されたインデックスの場合、常に直感的とは限らない正しいインデックス名を使用してください。存在しないインデックスを削除しようとすると、 になりますMongoCommandException。コレクション内のドキュメントの一意性が確保されるため、default _idインデックスを削除することはできません。

次のコード例は、インデックスが作成されたフィールド名を指定するか、すべてのインデックスを削除することで、インデックスを削除する方法を示しています。

String indexName = "unique_restaurantId_idx"; Document keys = new Document("cuisine", 1); // Drop index by name collection.dropIndex(indexName); // Drop index by keys collection.dropIndex(keys); // Drop all indexes collection.dropIndexes();

複数のキーを使用してインデックスを削除する場合は、指定されたすべてのキーを含む複合インデックスがあり、キーの順序が正しいことを確認してください。上記のインデックス作成サンプルコードは、「cuisine」および 機能の複合キーを示しています。その複合キーを削除しようとしても、その順序が作成に使用された順序ではない場合、MongoCommnadException エラーは次のように発生します。

Document keys = new Document("features", 1) .append("cuisine", 1); try { // Drop index by keys collection.dropIndex(keys); System.out.println("Successfully dropped index with keys: " + keys.toJson()); } catch (MongoCommandException commErr) { System.out.println("Error dropping index: " + commErr.getErrorMessage()); throw new RuntimeException("MongoCommandException was thrown while dropping index", commErr); }

次のエラーが表示されます。

Error dropping index: Cannot drop index: index not found. Tests run: 3, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.819 sec <<< FAILURE! com.amazon.docdb.guide.DocDBGuideTest.testindexGuide() Time elapsed: 0.817 sec <<< FAILURE! org.opentest4j.AssertionFailedError: Unexpected exception thrown: java.lang.RuntimeException: MongoCommandException was thrown while dropping index

インデックス選択の決定とインデックスヒントの提供

Amazon DocumentDB の説明機能を操作することは、クエリのパフォーマンスとインデックスの使用法を理解するために不可欠です。クエリを実行するときに、 explain()メソッドを追加して、どのインデックスが使用されているかなど、クエリプランに関する詳細情報を取得できます。explain() 出力は、クエリ実行ステージ、調査されたドキュメントの数、各ステージにかかる時間に関するインサイトを提供します。この情報は、特定のインデックスが効果的に使用されているかどうか、またはクエリが別のインデックス構造から恩恵を受けることができるかどうかを識別するのに非常に役立ちます。

explain() メソッドは、 find()メソッドと連鎖できます。explain() メソッドは、 ExplainVerbosity によって返される詳細レベルを決定するオプションの列挙型を取ることができますexplain()。現時点では、 EXECUTION_STATSおよび QUERY_PLANNER 列挙子のみが DocumentDB でサポートされています。次のコード例は、特定のクエリのクエリプランナーを取得する方法を示しています。

// Query we want to analyze Document query = new Document() .append("cuisine", "Thai") .append("rating.average", new Document("$gte", 4.0)); Document allPlansExplain = collection.find(query).explain(ExplainVerbosity.QUERY_PLANNER); System.out.println("All Plans Explain:\n" + allPlansExplain.toJson());

クエリプランナーの詳細レベルには、次の JSON ドキュメントが返されます。

{ "queryPlanner": { "plannerVersion": 1, "namespace": "ProgGuideData.Restaurants", "winningPlan": { "stage": "IXSCAN", "indexName": "cuisine_idx", "direction": "forward" } }, "serverInfo": { "host": "guidecluster3", "port": 27017, "version": "5.0.0" }, "ok": 1, "operationTime": { "$timestamp": { "t": 1739221668, "i": 1 } } }

Amazon DocumentDB が特定のインデックスを使用するように影響または強制するには、いくつかのオプションがあります。hint() および hintString()メソッドを使用すると、クエリに使用するインデックスを明示的に指定することで、クエリオプティマイザのデフォルトのインデックス選択動作を上書きできます。DocumentDB のクエリオプティマイザは通常、インデックスの選択に適切な選択を行いますが、歪んだデータを扱うときやインデックスのパフォーマンスをテストするときなど、特定のインデックスを hint()または で強制することがhintString()有益なシナリオがあります。

次のコード例では、上記のコードで実行されたのと同じクエリに対して複合インデックス「cuisine_features_idx」を強制的に使用します。

// Query we want to analyze Document query = new Document() .append("cuisine", "Thai") .append("rating.average", new Document("$gte", 4.0)); List < Document > queryDocs = new ArrayList < > (); collection.find(query).hintString("cuisine_features_idx").forEach(doc - > queryDocs.add(doc));