Docs Menu
Docs Home
/ /

Sparse Indexes

スパース インデックスには、インデックス フィールドに null 値が含まれていても、インデックスフィールドを持つドキュメントのエントリのみが含まれます。インデックスは、インデックス付きフィールドが欠落しているドキュメントをスキップします。コレクションのすべてのドキュメントが含まれているわけではないため、インデックスは "スパース" です。一方、非スパース インデックスにはコレクション内のすべてのドキュメントが含まれ、インデックス フィールドを含まないドキュメントには null 値がストアされます。

重要

部分インデックスはスパースインデックスとして機能できますが、フィールドが存在するかどうかを超える条件のフィルター式もサポートします。正確なフィルタリングが必要な場合は、より詳細な制御を行うために 部分インデックスを使用してください。

スパース インデックスを作成するには、sparse オプションを true に設定した db.collection.createIndex() メソッドを使用します。

たとえば、 mongoshの次の操作では、movies コレクションの plot フィールドにsparse indexが作成されます。

db.movies.createIndex( { "plot": 1 }, { sparse: true } )

インデックスは、plot フィールドを含まないドキュメントをインデックスしません。

注意

MongoDB のスパース インデックスと、他のデータベースのブロックレベル インデックスを混同しないでください。特定のフィルターを備えた密なインデックスと考えてください。

スパース インデックスによって、クエリやソート操作の結果セットが不完全になる場合、hint() で明示的にインデックスを指定しない限り、MongoDB はそのインデックスを使用しません。

たとえば、クエリ { plot: { $exists: false } } では、明示的なヒントがない限り plot フィールドにスパース インデックスを使用しません。動作の詳細を示す例については、「コレクションのスパース インデックスが完全な結果を返さない」を参照してください。

コレクション内のすべてのドキュメントの count() を実行するときに、スパース インデックスを指定する hint() を含めると(つまり、クエリ述語が空の場合)、スパース インデックスの結果が不正確なカウントになった場合でも、スパース インデックスが使用されます。

例、moviesコレクションの ratedフィールドにスパースインデックスを作成します。

db.movies.createIndex( { rated: 1 }, { sparse: true } )

moviesコレクション内のドキュメントの数をカウントし、その スパースインデックスを指定するヒントを含めると、操作はratedフィールドを含むドキュメントのみを返します。

db.movies.countDocuments( {}, { hint: { rated: 1 } } )

moviesコレクション内のドキュメント数の正確なカウントを取得するには、コレクション内のすべてのドキュメントのカウントを実行するときに、スパースインデックスを使用してhint() を実行しないでください。

db.movies.countDocuments()

次のインデックスの種類は、常にスパースです。

複合インデックスには、さまざまなタイプのスパースインデックスを含めることができます。インデックスのタイプの組み合わせによって、複合インデックスがドキュメントと一致する方法が決まります。

下表には、さまざまなタイプのスパースインデックスを含む複合インデックスの動作がまとめられています。

複合インデックスの構成要素
複合インデックスの動作
Ascending indexes
Descending indexes

1 つ以上のキーの値を含むドキュメントのみ、インデックスが作成されます。

Ascending indexes
Descending indexes

geospatial フィールドのいずれかに値が含まれている場合にのみ、ドキュメントのインデックスが作成されます。昇順または降順インデックス形式のドキュメントのインデックスは作成されません。

Ascending indexes
Descending indexes

text フィールドのいずれかに一致するドキュメントのみ、インデックスが作成されます。昇順または降順インデックス形式のドキュメントのインデックスは作成されません。

インデックスがスパースかつ一意の場合、フィールドの値が重複するドキュメントがコレクションに含まれることはありませんが、キーが省略された複数のドキュメントは許可されます。

次の例では、フィールドpassword にスパースインデックスを作成しています。

db.users.createIndex( { password: 1 } , { sparse: true } )

次に、usersコレクションに対する次のクエリは、スパースインデックスを使用して、passwordフィールドを持つドキュメントを返します。

db.users.find( { password: { $exists: true } } ).sort({ password: 1 }).limit(5)

ユーザーに passwordフィールドが含まれていない場合、クエリはそのユーザーを返しません。

一部のドキュメントには plotフィールドがない場合がある moviesコレクションについて考えてみましょう。

次の例では、フィールドplot にスパースインデックスを作成しています。

db.movies.createIndex( { "plot": 1 }, { sparse: true } )

movies コレクションのすべてのドキュメントを plot フィールドでソートして返すには、次のクエリを考慮します:

db.movies.find().sort( { plot: -1 } )

インデックス付きフィールドで並べ替えても、 コレクション内の一部のドキュメントには フィールドがない場合、 MongoDB は完全な結果を返すことを目的としてクエリを満たすために、スパースインデックスを選択することはmoviesplot ありません

スパース インデックスを使用するには、hint() を使用してインデックスを明示的に指定します。

db.movies.find().sort( { plot: -1 } ).hint( { plot: 1 } ).limit(5)

このクエリは、plotフィールドを含む moviesコレクション内のドキュメントのみを返します。

Tip

次の操作では、 フィールドに 一意の制約 とスパースフィルターを持つインデックスが作成されます。passwordusers

db.users.createIndex( { password: 1 } , { sparse: true, unique: true } )

このインデックスにより、password フィールドにユニークな値を持つドキュメント、あるいは password フィールドが含まれていないドキュメントの挿入が許可されます。そのため、users コレクション内の既存のドキュメントを前提として、インデックスでは以下の挿入操作が可能です。

db.users.insertMany( [
{ "name": "Jon Snow", "email": "jon@gameofthron.es", "password": "$2b$12$newHashedPassword1234567890ABC" },
{ "name": "Sansa Stark", "email": "sansa@gameofthron.es", "password": "$2b$12$anotherNewPassword1234567890DEF" },
{ "name": "Bran Stark", "email": "bran@gameofthron.es" }
] )

ただし、インデックスではコレクションにすでに存在するメールアドレスを含むドキュメントの追加は 許可されません

MongoDB5.0 以降、 キー パターン が同じ 一意のスパース および 一意の非スパース インデックスを単一コレクションに混在させることができます。

次の例では、キー パターンが同じで sparse オプションが異なる複数のインデックスを作成します。

db.users.createIndex( { password : 1 }, { name: "unique_index", unique: true } )
db.users.createIndex( { password : 1 }, { name: "unique_sparse_index", unique: true, sparse: true } )

スパース オプションの有無にかかわらず、同じキー パターンで基本インデックスを作成することもできます。

db.users.createIndex( { password : 1 }, { name: "sparse_index", sparse: true } )
db.users.createIndex( { password : 1 }, { name: "basic_index" } )

戻る

部分

項目一覧