Indexes
項目一覧
Overview
このガイドでは、MongoDB Java ドライバーでインデックスを使用する方法を学習できます。
インデックスは、MongoDB でクエリを効率的に実行するのに役立ちます。 インデックスがないと、MongoDB はコレクション内のすべてのドキュメントをスキャンする必要があります(コレクションスキャン)。 これらのコレクションスキャンは遅く、アプリケーションのパフォーマンスに悪影響を与える可能性があります。 クエリに適切なインデックスがある場合、MongoDB ではそのインデックスを使用して検査する必要があるドキュメントの数を制限できます。
インデックスも:
Tip
インデックスは、アップデートするドキュメントを見つけるときはアップデート操作、削除するドキュメントを見つけた場合は削除操作、および 集計パイプライン の特定のステージでも使用されます。
クエリ範囲とパフォーマンス
MongoDB に対してクエリを実行する場合、 コマンドにはさまざまな要素を含めることができます。
検索するフィールドと値を指定するクエリ条件
クエリの実行に影響するオプション(例: 読み取り保証 (read concern))
MongoDB が返すフィールドを指定するためのプロジェクション基準(任意)
MongoDB から返される順序ドキュメントを指定するためのソート基準(任意)
クエリ、プロジェクション、ソートで指定されたすべてのフィールドが同じインデックスにある場合、MongoDB はインデックスから直接結果を返します。これはカバード クエリとも呼ばれます。
重要
並び替え順
ソート条件は、インデックスの順序と一致するか、その順序を逆にする必要があります。
name
昇順(AZ)でフィールドage
と降順(9-0)のフィールド のインデックスを検討します。
name_1_age_-1
MongoDB は、次のいずれかでデータをソートするときにこのインデックスを使用します。
name
昇順、age
降順name
降順、age
の昇順
name
と ageの昇順、またはnameとage
の降順の並べ替え順序を指定するには、メモリ内でソートする必要があります。
インデックスがクエリ条件とプロジェクションをカバーするようにする方法に関する詳細については、MongoDB マニュアルのクエリ カバレッジ に関する記事を参照してください。
操作上の考慮事項
クエリのパフォーマンスを向上させるには、ソートされた結果を返すアプリケーションのクエリや操作で頻繁に表示されるフィールドにインデックスをビルドします。 追加する各インデックスはアクティブな場合にディスク領域とメモリを消費するため、キャパシティー プランニングのためにインデックス メモリとディスクの使用量を追跡する必要があります。 さらに、書込み操作によってインデックス フィールドが更新される場合、MongoDB は関連するインデックスも更新する必要があります。
MongoDB は動的スキーマをサポートしているため、アプリケーションは名前が事前に確認できないフィールドや任意のフィールドに対してクエリを実行できます。 MongoDB 4.2では、これらのクエリをサポートするためにワイルドカード インデックスが導入されています。 ワイルドカード インデックスは、ワークロードベースのインデックス プランニングを置き換えるように設計されていません。
データモデルの設計とアプリケーションに適したインデックスの選択の詳細については、「 MongoDB Server のデータ モデリングとインデックス 」を参照してください。
インデックス タイプ
MongoDB は、データのクエリをサポートするためにさまざまなインデックス タイプをサポートしています。 以下のセクションでは、最も一般的なインデックス型について説明し、各インデックス型を作成するためのサンプルコードを示します。 インデックス タイプの完全なリストについては、「インデックス 」を参照してください。
Tip
次の例では createIndex() メソッド を メソッドを使用してさまざまなインデックスを作成し、次の設定を行います。
import com.mongodb.DuplicateKeyException; import com.mongodb.MongoCommandException; import com.mongodb.client.*; import com.mongodb.client.model.IndexOptions; import com.mongodb.client.model.Indexes; import com.mongodb.client.model.Sorts; import com.mongodb.client.model.geojson.Point; import com.mongodb.client.model.geojson.Position; import org.apache.log4j.BasicConfigurator; import org.bson.Document; import org.bson.conversions.Bson; import static com.mongodb.client.model.Filters.*; import static com.mongodb.client.model.Projections.*;
final String uri = "mongodb+srv://<atlas-uri>/<dbname>?retryWrites=true&w=majority"; mongoClient = MongoClients.create(uri); database = mongoClient.getDatabase("sample_mflix"); collection = database.getCollection("movies");
単一フィールドと複合インデックス
単一フィールド インデックス
単一フィールド インデックスは、コレクションのドキュメント内の単一のフィールドを参照するインデックスです。 単一フィールド クエリとソートのパフォーマンスが向上し、一定時間の経過後または特定のクロック時間にコレクションからドキュメントを自動的に排除するTTL インデックスをサポートします。
注意
_id_
インデックスは、単一フィールド インデックスの例です。 このインデックスは、新しいコレクションが作成されるときに、 _id
フィールドに自動的に作成されます。
次の例では、 title
フィールドに昇順のインデックスを作成します。
String resultCreateIndex = collection.createIndex(Indexes.ascending("title")); System.out.println(String.format("Index created: %s", resultCreateIndex));
以下は、前のコード スニペットで作成されたインデックスによってカバーされるクエリの例です。
Bson filter = eq("title", "Batman"); Bson sort = Sorts.ascending("title"); Bson projection = fields(include("title"), excludeId()); FindIterable<Document> cursor = collection.find(filter).sort(sort).projection(projection);
複合インデックス
複合インデックス は、コレクションのドキュメント内の複数のフィールドへの参照を保持し、クエリとソートのパフォーマンスを向上させます。
Tip
複合インデックス、インデックス プレフィックス、ソート順序の詳細については、こちらをご覧ください。
次の例では、 フィールドと フィールドに複合インデックスを作成しています。type
rated
String resultCreateIndex = collection.createIndex(Indexes.ascending("type", "rated")); System.out.println(String.format("Index created: %s", resultCreateIndex));
以下は、前のコード スニペットで作成されたインデックスによってカバーされるクエリの例です。
Bson filter = and(eq("type", "movie"), eq("rated", "G")); Bson sort = Sorts.ascending("type", "rated"); Bson projection = fields(include("type", "rated"), excludeId()); FindIterable<Document> cursor = collection.find(filter).sort(sort).projection(projection);
詳細については、 マニュアルの「 複合インデックス MongoDB Server」を参照してください。
マルチキー インデックス(配列フィールドへのインデックス)
マルチキー インデックスは、配列値を含むインデックスを持つフィールドを指定するクエリのパフォーマンスを向上させるインデックスです。 単一フィールドまたは複合インデックスと同じ構文を使用してマルチキー インデックスを定義できます。
次の例では、 rated
、 genres
(文字列の配列)、 title
フィールドに複合マルチキー インデックスを作成します。
String resultCreateIndex = collection.createIndex(Indexes.ascending("rated", "genres", "title")); System.out.println(String.format("Index created: %s", resultCreateIndex));
以下は、前のコード スニペットで作成されたインデックスによってカバーされるクエリの例です。
Bson filter = and(eq("genres", "Animation"), eq("rated", "G")); Bson sort = Sorts.ascending("title"); Bson projection = fields(include("title", "rated"), excludeId()); FindIterable<Document> cursor = collection.find(filter).sort(sort).projection(projection);
マルチキー インデックスは、クエリ カバレッジ、インデックスバウンド計算、およびソート動作の点で他のインデックスとは動作が異なります。 マルチキー インデックス(動作や制限事項を含む)について詳しくは、MongoDB マニュアルの「 マルチキー インデックス 」のページを参照してください。
Text Indexes
テキスト インデックスは、string コンテンツに対するテキスト検索クエリをサポートします。 これらのインデックスには、値が string または複数の string 配列である任意のフィールドを含めることができます。 MongoDB はさまざまな言語のテキスト検索をサポートしています。 インデックスの作成時に、オプションとしてデフォルト言語を指定できます。
Tip
テキスト インデックスは、より強力なAtlas Full Text Searchインデックスとは異なります。 Atlas ユーザーは Atlas Search を使用する必要があります。
シングル フィールド
次の例では、 plot
フィールドに テキスト インデックスを作成しています。
try { String resultCreateIndex = collection.createIndex(Indexes.text("plot")); System.out.println(String.format("Index created: %s", resultCreateIndex)); // Prints a message if a text index already exists with a different configuration } catch (MongoCommandException e) { if (e.getErrorCodeName().equals("IndexOptionsConflict")) System.out.println("there's an existing text index with different options"); }
以下は、前のコード スニペットで作成されたインデックスを使用するクエリの例です。 テキスト インデックスにはソート順序が含まれていないため、 sort
は省略されていることに注意してください。
Bson filter = text("java coffee shop"); Bson projection = fields(include("fullplot"), excludeId()); FindIterable<Document> cursor = collection.find(filter).projection(projection);
複数のフィールド
コレクションには 1 つのテキスト インデックスしか含めることができません。 複数のテキストフィールドのテキストインデックスを作成する場合は、複合インデックスを作成する必要があります。 複合インデックス内のすべてのテキスト フィールドに対してテキスト検索が実行されます。
次のスニペットは、 フィールドと フィールドの複合テキストtitle
genre
インデックスを作成します。
collection.createIndex(Indexes.compoundIndex(Indexes.text("title"), Indexes.text("genre")));
詳細については、次のサーバー マニュアル エントリを参照してください。
地理空間インデックス
MongoDB は、 2 dsphere インデックスを使用した地理空間座標データのクエリをサポートしています。 2dsphere
インデックスを使用すると、包含、交差、近接性について地理空間データを照会できます。 地理空間データのクエリの詳細については、「地理空間クエリ 」を参照してください。
2dsphere
インデックスを作成するには、 GeoJSON オブジェクトのみを含むフィールドを指定する必要があります。 これについて詳しくは、MongoDB Server マニュアルの「 GeoJSON オブジェクト 」のページを参照してください。
sample_mflix
データベース内のtheaters
コレクションの次のサンプル ドキュメントのlocation.geo
フィールドは、劇場の座標を記述する GeoJSON ポイント オブジェクトです。
{ "_id" : ObjectId("59a47286cfa9a3a73e51e75c"), "theaterId" : 104, "location" : { "address" : { "street1" : "5000 W 147th St", "city" : "Hawthorne", "state" : "CA", "zipcode" : "90250" }, "geo" : { "type" : "Point", "coordinates" : [ -118.36559, 33.897167 ] } } }
次の例では、 location.geo
フィールドに2dsphere
インデックスを作成します。
重要
地理空間インデックスによってカバーされているフィールドに地理空間インデックスを作成しようとすると、エラーが発生します。
try { String resultCreateIndex = collection.createIndex(Indexes.geo2dsphere("location.geo")); System.out.println(String.format("Index created: %s", resultCreateIndex)); // Prints a message if a geospatial index already exists with a different configuration } catch (MongoCommandException e) { if (e.getErrorCodeName().equals("IndexOptionsConflict")) System.out.println("there's an existing geospatial index with different options"); }
以下は、「location.geo」を使用した地理空間クエリの例です。 インデックス。
// Stores the coordinates of the NY MongoDB headquarters Point refPoint = new Point(new Position(-73.98456, 40.7612)); // Retrieves documents that represent locations up to 1000 meters from the specified point directly from the geospatial index // Creates a filter to match a document Bson filter = near("location.geo", refPoint, 1000.0, 0.0); FindIterable<Document> cursor = collection.find(filter);
MongoDB は、ユークリッド平面上の距離を計算し、MongoDB 2.2以前で使用される「legacy coordinate pairs」構文を操作するための2d
インデックスもサポートしています。 詳細については、MongoDB Server マニュアルの「 地理空間クエリ 」ページ を参照してください。
Unique Indexes
ユニークインデックスにより、インデックス フィールドに重複する値が格納されなくなります。デフォルトでは、MongoDB はコレクションの作成時に _id
フィールドにユニークインデックスを作成します。ユニークインデックスを作成するには、重複を防ぐフィールドまたはフィールドの組み合わせを指定し、unique
オプションを true
に設定します。
次の例では、 theaterId
フィールドに一意の降順インデックスを作成しています。
try { IndexOptions indexOptions = new IndexOptions().unique(true); String resultCreateIndex = collection.createIndex(Indexes.descending("theaterId"), indexOptions); System.out.println(String.format("Index created: %s", resultCreateIndex)); // Prints a message if the "theaterID" field contains duplicate values } catch (DuplicateKeyException e) { System.out.printf("duplicate field values encountered, couldn't create index: \t%s\n", e); }
重要
一意なインデックスに違反する重複値を保存する書込み操作を実行すると、MongoDB Java ドライバーはDuplicateKeyException
を発生させ、MongoDB は次のようなエラーを返します。
E11000 duplicate key error index
ワイルドカード インデックス
ワイルドカード インデックスを使用すると、不明なフィールドや任意のフィールドに対するクエリが可能になります。 動的スキーマを使用している場合は、これらのインデックスが役立ちます。
次の例では、サブドキュメントや配列にネストされた値を含む、 location
フィールドのすべての値に対して昇順のワイルドカード インデックスを作成します。
String resultCreateIndex = collection.createIndex(Indexes.ascending("location.$**")); System.out.println(String.format("Index created: %s", resultCreateIndex));
詳細については、MongoDB Server マニュアルの「 ワイルドカード インデックス 」のページを参照してください。
クラスター化インデックス
クラスター化されたインデックスは、キー値の順にドキュメントを保存するようにコレクションに指示します。 クラスター化インデックスを作成するには、コレクションを作成するときに、 _id
フィールドをキーとして指定し、一意のフィールドをtrue
として指定して、 クラスター化インデックス オプション を指定します。
次の例では、 vendors
コレクションの_id
フィールドにクラスター化インデックスを作成しています。
MongoDatabase database = mongoClient.getDatabase("tea"); ClusteredIndexOptions clusteredIndexOptions = new ClusteredIndexOptions(new Document("_id", 1), true); CreateCollectionOptions createCollectionOptions = new CreateCollectionOptions().clusteredIndexOptions(clusteredIndexOptions); database.createCollection("vendors", createCollectionOptions);
詳細については、MongoDB Server マニュアルの各セクションを参照してください。
インデックスを削除する
_id
フィールドのデフォルトの一意なインデックスを除く未使用のインデックスを削除できます。
次のセクションでは、インデックスを削除する方法を示します。
インデックス仕様ドキュメントの使用
インデックス付き名前フィールドの使用
ワイルドカード文字を使用してすべてのインデックスを削除する
インデックス仕様ドキュメントを使用したインデックスの削除
インデックス仕様ドキュメントをdropIndex()
メソッドに渡して、コレクションからインデックスを削除します。 インデックス仕様ドキュメントは、指定されたフィールドのインデックスのタイプを指定するBson
インスタンスです。
次のスニペットは、 コレクションのtitle
フィールドの昇順のインデックスを削除します。
collection.dropIndex(Indexes.ascending("title"));
重要
テキスト インデックスを削除する場合は、代わりにインデックスの名前を使用する必要があります。 詳細については、「 名前フィールドを使用したインデックスの削除 」セクションを参照してください。
名前フィールドを使用したインデックスの削除
コレクションからインデックスを削除するには、インデックスのname
フィールドをdropIndex()
メソッドに渡します。
インデックスの名前を検索する必要がある場合は、 listIndexes()
メソッドを使用して、インデックス内のname
フィールドの値を確認します。
次のスニペットは、コレクション内のすべてのインデックスを検索して出力します。
collection.listIndexes().forEach(doc -> System.out.println(doc.toJson()));
テキスト インデックスを含むコレクションでlistIndex()
を呼び出すと、出力は次のようになります。
{ "v": 2, "key": {"_id": 1}, "name": "_id_" } { "v": 2, "key": {"_fts": "text", "_ftsx": 1}, "name": "title_text", "weights": {"title": 1}, "default_language": "english", "language_override": "language", "textIndexVersion": 3 }
この出力では、既存のインデックスの名前が "_id" と "title_text" であることがわかります。
次のスニペットは、 コレクションから "title_text" インデックスを削除します。
collection.dropIndex("title_text");
注意
複合テキスト インデックスから単一のフィールドを削除することはできません。 インデックス フィールドを更新するには、インデックス全体を削除し、新しいインデックスを作成する必要があります。
ワイルドカード文字を使用したインデックスの削除
MongoDB 4.2 以降では、コレクションでdropIndexes()
メソッドを呼び出すことで、すべてのインデックスを削除できます。
collection.dropIndexes();
以前のバージョンの MongoDB の場合は、コレクションのdropIndex()
への呼び出しに「*」をパラメータとして渡します。
collection.dropIndex("*");
このセクションのメソッドの詳細については、次の API ドキュメントを参照してください。