Indexes
項目一覧
Overview
このガイドでは、MongoDB Kotlin ドライバーを使用してインデックスを作成および管理する方法を学習できます。
インデックスは、MongoDB でクエリを効率的に実行するのに役立ちます。 インデックスがないと、MongoDB はコレクション内のすべてのドキュメントをスキャンする必要があります(コレクションスキャン)。 これらのコレクションスキャンは遅く、アプリケーションのパフォーマンスに悪影響を与える可能性があります。 クエリに適切なインデックスがある場合、MongoDB はそのインデックスを使用して、クエリが検査する必要があるドキュメントを制限できます。
また、インデックスには次の利点もあります。
インデックスを使用すると効率的なソートが可能になります。
インデックスにより、 地理空間クエリなどの特別な機能が有効になります。
インデックスを使用すると、フィールド値を一意のものにするための制約を作成できます。
詳細については、サーバー マニュアルの 「インデックス」 を参照してください。
Tip
更新操作では、アップデートするドキュメントが見つかるとインデックスが使用され、削除操作では、削除するドキュメントが見つかるとインデックスが使用されます。 集計パイプラインの特定のステージでは、パフォーマンスを向上させるためにインデックスも使用します。
クエリ範囲とパフォーマンス
MongoDB に対してクエリを実行する場合、 コマンドにはさまざまな要素を含めることができます。
検索するフィールドと値を指定するクエリ条件
読み取り保証など、クエリの実行に影響するオプション
MongoDB が返すフィールドを指定するためのプロジェクション基準(任意)
MongoDB から返されるドキュメントの順序を指定するためのソート基準(任意)
クエリ、プロジェクション、ソートで指定されたすべてのフィールドが同じインデックスにある場合、MongoDB はインデックスから直接結果を返します。これはカバード クエリとも呼ばれます。
重要
並び替え順
ソート条件は、インデックスの順序と一致するか、その順序を逆にする必要があります。
name
昇順(AZ)でフィールドage
と降順(9-0)のフィールド のインデックスを検討します。
name_1_age_-1
MongoDB は、次のいずれかの方法でデータをソートするときにこのインデックスを使用します。
name
昇順、age
降順name
降順、age
の昇順
name
と ageの昇順、またはnameとage
の降順の並べ替え順序を指定するには、メモリ内でソートする必要があります。
インデックスがクエリ条件とプロジェクションをカバーするようにする方法の詳細については、サーバー マニュアルの「クエリ カバレッジ 」に関する記事を参照してください。
操作上の考慮事項
次のガイドラインでは、アプリケーションでインデックスを使用する方法を最適化する方法について説明します。
クエリのパフォーマンスを向上させるには、ソートされた結果を返すアプリケーションのクエリや操作で頻繁に表示されるフィールドにインデックスを構築します。
追加する各インデックスは、アクティブにディスク領域とメモリを消費するため、キャパシティー プランニングのためにインデックス メモリとディスク使用量を追跡します。
使用頻度の低いインデックスは、追加しないようにしてください。 書込み操作によってインデックス付きフィールドが更新されると、MongoDB は関連するインデックスを更新することに注意してください。
MongoDB は動的スキーマをサポートしているため、アプリケーションは名前が事前に確認できないフィールドや任意のフィールドに対してクエリを実行できます。 MongoDB 4.2では、これらのクエリをサポートするためにワイルドカード インデックスが導入されています。 ワイルドカード インデックスは、ワークロードベースのインデックス プランニングを置き換えるように設計されていません。
データモデルの設計とアプリケーションに適したインデックスの選択の詳細については、MongoDB サーバーのドキュメントの「インデックス作成戦略」と「データ モデリングとインデックス 」を参照してください。
インデックス タイプ
MongoDB は、データのクエリをサポートするためにさまざまなインデックス タイプをサポートしています。 以下のセクションでは、最も一般的なインデックス型について説明し、各インデックス型を作成するためのサンプルコードを示します。 インデックス タイプの完全なリストについては、サーバー マニュアルの「インデックス」を参照してください。
Tip
Kotlinドライバーは、インデックスを作成および管理するための Indexes クラスを提供します。このクラスには、さまざまなMongoDBインデックスキー タイプのインデックス仕様ドキュメントを作成するための静的ファクトリー メソッドが含まれています。
次の例では createIndex() メソッド を メソッドを使用してさまざまなインデックスを作成し、次のデータ クラスを使用して MongoDB のデータをモデル化します。
// Data class for the movies collection data class Movie( val title: String, val year: Int, val cast: List<String>, val genres: List<String>, val type: String, val rated: String, val plot: String, val fullplot: String, ) // Data class for the theaters collection data class Theater( val theaterId: Int, val location: Location ) { data class Location( val address: Address, val geo: Point ) { data class Address( val street1: String, val city: String, val state: String, val zipcode: String ) } }
単一フィールドと複合インデックス
単一フィールド インデックス
単一フィールド インデックスは、コレクションのドキュメント内の単一のフィールドを参照するインデックスです。 単一フィールド クエリとソートのパフォーマンスが向上し、一定時間の経過後または特定のクロック時間にコレクションからドキュメントを自動的に排除するTTL インデックスをサポートします。
注意
_id_
インデックスは、単一フィールド インデックスの例です。 このインデックスは、新しいコレクションが作成されるときに、 _id
フィールドに自動的に作成されます。
次の例では、 title
フィールドに昇順のインデックスを作成します。
val resultCreateIndex = moviesCollection.createIndex(Indexes.ascending(Movie::title.name)) println("Index created: $resultCreateIndex")
Index created: title_1
以下は、前のコード スニペットで作成されたインデックスによってカバーされるクエリの例です。
val filter = Filters.eq(Movie::title.name, "The Dark Knight") val sort = Sorts.ascending(Movie::title.name) val projection = Projections.fields( Projections.include(Movie::title.name), Projections.excludeId() ) data class Results(val title: String) val resultsFlow = moviesCollection.find<Results>(filter).sort(sort).projection(projection) resultsFlow.collect { println(it) }
詳細については、 MongoDB サーバー マニュアルの単一フィールド インデックスのセクションを参照してください。
複合インデックス
複合インデックス は、コレクションのドキュメント内の複数のフィールドへの参照を保持し、クエリとソートのパフォーマンスを向上させます。
Tip
複合インデックス、インデックス プレフィックス、ソート順序の詳細については、こちらをご覧ください。
次の例では、 フィールドと フィールドに複合インデックスを作成しています。type
rated
val resultCreateIndex = moviesCollection.createIndex(Indexes.ascending(Movie::type.name, Movie::rated.name)) println("Index created: $resultCreateIndex")
Index created: type_1_rated_1
以下は、前のコード スニペットで作成されたインデックスによってカバーされるクエリの例です。
val filter = Filters.and( Filters.eq(Movie::type.name, "movie"), Filters.eq(Movie::rated.name, "G") ) val sort = Sorts.ascending(Movie::type.name, Movie::rated.name) val projection = Projections.fields( Projections.include(Movie::type.name, Movie::rated.name), Projections.excludeId() ) val resultsFlow = moviesCollection.find(filter).sort(sort).projection(projection) resultsFlow.collect { println(it) }
詳細については、MongoDB サーバーのマニュアルの「複合インデックス」のセクションを参照してください。
マルチキー インデックス(配列フィールドへのインデックス)
マルチキー インデックスは、配列値を含むインデックスを持つフィールドを指定するクエリのパフォーマンスを向上させるインデックスです。 単一フィールドまたは複合インデックスと同じ構文を使用してマルチキー インデックスを定義できます。
次の例では、 rated
、 genres
(文字列の配列)、 title
フィールドに複合マルチキー インデックスを作成します。
val resultCreateIndex = moviesCollection.createIndex(Indexes.ascending(Movie::rated.name, Movie::genres.name, Movie::title.name)) println("Index created: $resultCreateIndex")
Index created: rated_1_genres_1_title_1
以下は、前のコード スニペットで作成されたインデックスによってカバーされるクエリの例です。
val filter = Filters.and( Filters.eq(Movie::genres.name, "Animation"), Filters.eq(Movie::rated.name, "G") ) val sort = Sorts.ascending(Movie::title.name) val projection = Projections.fields( Projections.include(Movie::title.name, Movie::rated.name), Projections.excludeId() ) val resultsFlow = moviesCollection.find(filter).sort(sort).projection(projection) resultsFlow.collect { println(it) }
マルチキー インデックスは、クエリ カバレッジ、インデックスバウンド計算、およびソート動作の点で他のインデックスとは動作が異なります。 マルチキー インデックス(動作や制限事項を含む)の詳細については、サーバー マニュアルの「 マルチキーインデックス」を参照してください。
Atlas Search と Vector Search インデックス
Kotlin ドライバーを使用すると、Atlas Search および Atlas Vector Search インデックスをプログラムで管理できます。
Atlas Search 機能を使用すると、MongoDB Atlas でホストされているコレクションに対して全文検索を実行できます。 MongoDB Atlas Search の詳細については、「 Atlas Search インデックス」のドキュメントを参照してください。
Atlas Vector Search を使用すると、MongoDB Atlas に保存されているベクトル埋め込みに対してセマンティック検索を実行できます。 Atlas Vector Search の詳細については、集計ビルダ ガイドの Atlas Vector Searchセクションを参照してください。
コレクションに対して次のメソッドを呼び出して、Atlas Search インデックスと Vector Search インデックスを管理できます。
createSearchIndex()
(検索インデックスでのみ有効)createSearchIndexes()
listSearchIndexes()
updateSearchIndex()
dropSearchIndex()
注意
Atlas Search インデックス マネジメントのメソッドは非同期で実行されます。 ドライバー メソッドは、正常に実行されたことを確認する前に戻ることができます。 インデックスの現在のステータスを確認するには、 listSearchIndexes()
メソッドを呼び出します。
次のセクションでは、前述の各メソッドの使用方法を示すコード例を示します。
検索インデックスを作成
createSearchIndex() メソッドを使用して、単一の Atlas Searchインデックスを作成できます。このメソッドを使用してベクトル検索インデックスを作成することはできません。
createSearchIndexes() メソッドを使用して、複数の Atlas Search またはベクトル検索インデックスを作成できます。各インデックスに対して SearchIndexModelインスタンスを作成し、 インスタンスのリストをSearchIndexModel
createSearchIndexes()
メソッドに渡す必要があります。
次のコード例は、Atlas Search インデックスの作成方法を示しています。
val searchIdx = Document( "mappings", Document("dynamic", true) ) val resultCreateIndex = moviesCollection.createSearchIndex("myIndex", searchIdx)
複数の検索インデックスまたはベクトル検索インデックスを作成するには、 SearchIndexModel を作成する必要があります 各インデックスの インスタンス。
次のコード例は、1 回の呼び出しで検索インデックスとベクトル検索インデックスを作成する方法を示しています。
val searchIdxMdl = SearchIndexModel( "searchIdx", Document("analyzer", "lucene.standard").append( "mappings", Document("dynamic", true) ), SearchIndexType.search() ) val vectorSearchIdxMdl = SearchIndexModel( "vsIdx", Document( "fields", listOf( Document("type", "vector") .append("path", "embeddings") .append("numDimensions", 1536) .append("similarity", "dotProduct") ) ), SearchIndexType.vectorSearch() ) val resultCreateIndexes = moviesCollection.createSearchIndexes( listOf(searchIdxMdl, vectorSearchIdxMdl) )
検索インデックスをリストする
listSearchIndexes() を使用できます メソッドを使用して、コレクションの Atlas Search インデックスのリストを返します。
次のコード例は、コレクションの検索インデックスのリストを出力する方法を示しています。
val searchIndexesList = moviesCollection.listSearchIndexes().toList()
検索インデックスをアップデートする
updateSearchIndex() を使用できます Atlas Search インデックスを更新する方法。
次のコードは、検索インデックスを更新する方法を示しています。
moviesCollection.updateSearchIndex( "myIndex", Document("analyzer", "lucene.simple").append( "mappings", Document("dynamic", false) .append( "fields", Document( "title", Document("type", "string") ) ) ) )
検索インデックスを削除する
dropSearchIndex() を使用できます メソッドを使用して、Atlas Search インデックスを削除します。
次のコードは、コレクションから検索インデックスを削除する方法を示しています。
moviesCollection.dropSearchIndex("myIndex");
Text Indexes
テキスト インデックスは、string コンテンツに対するテキスト検索クエリをサポートします。 これらのインデックスには、値が string または複数の string 配列である任意のフィールドを含めることができます。 MongoDB はさまざまな言語のテキスト検索をサポートしています。 インデックスの作成時に、オプションとしてデフォルト言語を指定できます。
Tip
MongoDB は、改良された全文検索ソリューションであるAtlas Searchを提供します。 Atlas Search インデックスとその使用方法の詳細については、このガイドの「Atlas Search と Vector Search インデックス 」セクションを参照してください。
シングル フィールド
次の例では、 plot
フィールドに テキスト インデックスを作成しています。
try { val resultCreateIndex = moviesCollection.createIndex(Indexes.text(Movie::plot.name)) println("Index created: $resultCreateIndex") } catch (e: MongoCommandException) { if (e.errorCodeName == "IndexOptionsConflict") { println("there's an existing text index with different options") } }
Index created: plot_text
以下は、前のコード スニペットで作成されたインデックスによってカバーされるクエリの例です。 テキスト インデックスにはソート順序が含まれていないため、 sort
は省略されていることに注意してください。
val filter = Filters.text("Batman") val projection = Projections.fields( Projections.include(Movie::fullplot.name), Projections.excludeId() ) data class Results(val fullplot: String) val resultsFlow = moviesCollection.find<Results>(filter).projection(projection) resultsFlow.collect { println(it) }
複数のフィールド
コレクションには 1 つのテキスト インデックスしか含めることができません。 複数のテキストフィールドのテキストインデックスを作成する場合は、複合インデックスを作成する必要があります。 複合インデックス内のすべてのテキスト フィールドに対してテキスト検索が実行されます。
次のスニペットは、 フィールドと フィールドの複合テキストtitle
genre
インデックスを作成します。
try { val resultCreateIndex = moviesCollection.createIndex( Indexes.compoundIndex( Indexes.text(Movie::title.name), Indexes.text(Movie::genres.name) ) ) println("Index created: $resultCreateIndex") } catch (e: MongoCommandException) { if (e.errorCodeName == "IndexOptionsConflict") { println("there's an existing text index with different options") } }
Index created: title_text_genre_text
詳細については、次のサーバー マニュアル エントリを参照してください。
地理空間インデックス
MongoDB は、 2 dsphere インデックスを使用した地理空間座標データのクエリをサポートしています。 2dsphere
インデックスを使用すると、包含、交差、近接性について地理空間データを照会できます。 地理空間データのクエリの詳細については、サーバー マニュアルの「地理空間クエリ」を参照してください。
2dsphere
インデックスを作成するには、 GeoJSON オブジェクトのみを含むフィールドを指定する必要があります。 このタイプの詳細については、サーバー マニュアルの 「 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
インデックスを作成します。
val resultCreateIndex = theatersCollection.createIndex( Indexes.geo2dsphere("${Theater::location.name}.${Theater.Location::geo.name}") ) println("Index created: $resultCreateIndex")
Index created: location.geo_2dsphere
重要
すでに地理空間インデックスでカバーされているフィールドに地理空間インデックスを作成しようとすると、エラーが発生します。
以下は、前のコード スニペットで作成されたインデックスによってカバーされる地理空間クエリの例です。
// MongoDB Headquarters in New York, NY. val refPoint = Point(Position(-73.98456, 40.7612)) val filter = Filters.near( "${Theater::location.name}.${Theater.Location::geo.name}", refPoint, 1000.0, 0.0 ) val resultsFlow = theatersCollection.find(filter) resultsFlow.collect { println(it) }
MongoDB は、ユークリッド平面上の距離を計算し、MongoDB 2.2以前で使用される「legacy coordinate pairs」構文を操作するための2d
インデックスもサポートしています。 詳細については、サーバー マニュアルの 「地理空間クエリ」 を参照してください。
Unique Indexes
ユニークインデックスにより、インデックス フィールドに重複する値が格納されなくなります。デフォルトでは、MongoDB はコレクションの作成時に _id
フィールドにユニークインデックスを作成します。ユニークインデックスを作成するには、重複を防ぐフィールドまたはフィールドの組み合わせを指定し、unique
オプションを true
に設定します。
次の例では、 theaterId
フィールドに一意の降順インデックスを作成しています。
try { val indexOptions = IndexOptions().unique(true) val resultCreateIndex = theatersCollection.createIndex( Indexes.descending(Theater::theaterId.name), indexOptions ) println("Index created: $resultCreateIndex") } catch (e: DuplicateKeyException) { println("duplicate field values encountered, couldn't create index: \t${e.message}") }
Index created: theaterId_-1
重要
一意なインデックスに違反する重複値を保存する書込み操作を実行すると、ドライバーはDuplicateKeyException
を発生させ、MongoDB は次のようなエラーを返します。
E11000 duplicate key error index
詳細については、MongoDB サーバー マニュアルの [一意のインデックス ] ページを参照してください。
クラスター化インデックス
クラスター化されたインデックスは、キー値の順にドキュメントを保存するようにコレクションに指示します。 クラスター化インデックスを作成するには、コレクションを作成するときに、 _id
フィールドをキーとして指定し、一意のフィールドをtrue
として指定して、 クラスター化インデックス オプション を指定します。
次の例では、 vendors
コレクションの_id
フィールドにクラスター化インデックスを作成しています。
val clusteredIndexOptions = ClusteredIndexOptions(Document("_id", 1), true) val createCollectionOptions = CreateCollectionOptions().clusteredIndexOptions(clusteredIndexOptions) database.createCollection("vendors", createCollectionOptions)
詳細については、MongoDB サーバーのマニュアル セクションを参照してください。
インデックスを削除する
_id
フィールドのデフォルトの一意なインデックスを除く未使用のインデックスを削除できます。
次のセクションでは、インデックスを削除する方法を示します。
インデックス仕様ドキュメントの使用
インデックス付き名前フィールドの使用
ワイルドカード文字を使用してすべてのインデックスを削除する
インデックス仕様ドキュメントを使用したインデックスの削除
インデックス仕様ドキュメントをdropIndex()
メソッドに渡して、コレクションからインデックスを削除します。 インデックス仕様ドキュメントは、指定されたフィールドのインデックスのタイプを指定するBson
インスタンスです。
次のスニペットは、 コレクションのtitle
フィールドの昇順のインデックスを削除します。
moviesCollection.dropIndex(Indexes.ascending(Movie::title.name));
重要
テキスト インデックスを削除する場合は、代わりにインデックスの名前を使用する必要があります。 詳細については、「 名前フィールドを使用したインデックスの削除 」セクションを参照してください。
名前フィールドを使用したインデックスの削除
コレクションからインデックスを削除するには、インデックスのname
フィールドをdropIndex()
メソッドに渡します。
インデックスの名前を見つける必要がある場合は、 listIndexes()
メソッドを使用して、インデックス内のname
フィールドの値を確認します。
次のスニペットは、コレクション内のすべてのインデックスを検索して出力します。
val indexes = moviesCollection.listIndexes() indexes.collect { println(it.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" インデックスを削除します。
moviesCollection.dropIndex("title_text")
注意
複合テキスト インデックスから単一のフィールドを削除することはできません。 インデックス フィールドを更新するには、インデックス全体を削除し、新しいインデックスを作成する必要があります。
ワイルドカード文字を使用したインデックスの削除
MongoDB 4.2 以降では、コレクションでdropIndexes()
メソッドを呼び出すことで、すべてのインデックスを削除できます。
moviesCollection.dropIndexes()
以前のバージョンの MongoDB の場合は、コレクションのdropIndex()
への呼び出しに「*」をパラメータとして渡します。
moviesCollection.dropIndex("*")
このセクションのメソッドの詳細については、次の API ドキュメントを参照してください。