Docs Menu
Docs Home
/
MongoDBマニュアル
/

ワイルドカード インデックス

項目一覧

  • ワイルドカード インデックスの作成
  • Considerations
  • 動作
  • 制限事項
  • ワイルドカード インデックス クエリ/ソートのサポート

MongoDB は、クエリをサポートするためにフィールドまたはフィールドのセットにインデックスを作成することをサポートしています。 MongoDB は動的スキーマをサポートしているため、アプリケーションは名前が事前に確認できないフィールドや任意のフィールドに対してクエリを実行できます。

バージョン MongoDB の新機能: 4.2

MongoDB 4.2 では、不明なフィールドや任意のフィールドに対するクエリをサポートするための ワイルドカード インデックス が導入されています。

userMetadataフィールドの下でユーザー定義データを取得し、そのデータに対するクエリをサポートするアプリケーションを考えてみましょう。

{ "userMetadata" : { "likes" : [ "dogs", "cats" ] } }
{ "userMetadata" : { "dislikes" : "pickles" } }
{ "userMetadata" : { "age" : 45 } }
{ "userMetadata" : "inactive" }

管理者は、 userMetadataの任意のサブフィールドに対するクエリをサポートするインデックスを作成したいと考えています。

userMetadataのワイルドカード インデックスは、 userMetadatauserMetadata.likesuserMetadata.dislikesuserMetadata.ageの単一フィールド クエリをサポートできます。

db.userData.createIndex( { "userMetadata.$**" : 1 } )

インデックスは次のクエリをサポートできます。

db.userData.find({ "userMetadata.likes" : "dogs" })
db.userData.find({ "userMetadata.dislikes" : "pickles" })
db.userData.find({ "userMetadata.age" : { $gt : 30 } })
db.userData.find({ "userMetadata" : "inactive" })

userMetadataの非ワイルドカード インデックスは、 userMetadataの値に対するクエリのみをサポートできます。

重要

ワイルドカード インデックスは、ワークロードベースのインデックス プランニングを置き換えるように設計されていません。 クエリをサポートするインデックスの作成の詳細については、「 クエリをサポートするインデックスの作成」を参照してください。 ワイルドカード インデックスの制限に関する詳細なドキュメントについては、「ワイルドカード インデックスの制限 」を参照してください。

重要

ワイルドカード インデックスを作成するには、 mongod featureCompatibilityVersion4.2である必要があります。 fCV を設定する手順については、「 MongoDB 5.0 配置で機能の互換性バージョンを設定する 」を参照してください。

ワイルドカード インデックスは、 createIndexesデータベースコマンドまたはそのshellヘルパー( createIndex()またはcreateIndexes() を使用して作成できます。

特定のフィールドの値をインデックス化するには:

db.collection.createIndex( { "fieldA.$**" : 1 } )

このワイルドカード インデックスを使用すると、MongoDB はfieldAのすべての値をインデックス化します。 フィールドがネストされたドキュメントまたは配列の場合、ワイルドカード インデックスはドキュメントまたは配列に再帰し、ドキュメントまたは配列内のすべてのフィールドの値を保存します。

たとえば、 product_catalogコレクション内のドキュメントにはproduct_attributesフィールドが含まれている場合があります。 product_attributesフィールドには、埋め込みドキュメントや配列など、任意のネストされたフィールドを含めることができます。

{
"product_name" : "Spy Coat",
"product_attributes" : {
"material" : [ "Tweed", "Wool", "Leather" ]
"size" : {
"length" : 72,
"units" : "inches"
}
}
}
{
"product_name" : "Spy Pen",
"product_attributes" : {
"colors" : [ "Blue", "Black" ],
"secret_feature" : {
"name" : "laser",
"power" : "1000",
"units" : "watts",
}
}
}

次の操作を実行すると、product_attributes フィールドでワイルドカード インデックスが作成されます。

db.products_catalog.createIndex( { "product_attributes.$**" : 1 } )

ワイルドカード インデックスは、 product_attributesまたはその埋め込みフィールドに対する任意の単一フィールド クエリをサポート可能です。

db.products_catalog.find( { "product_attributes.size.length" : { $gt : 60 } } )
db.products_catalog.find( { "product_attributes.material" : "Leather" } )
db.products_catalog.find( { "product_attributes.secret_feature.name" : "laser" } )

注意

パス固有のワイルドカード インデックス構文はwildcardProjectionオプションと互換性がありません。 詳細についてはwildcardインデックスのオプション を参照してください。

例については、「単一フィールドパスでのワイルドカード インデックスの作成 」を参照してください。

ドキュメント内のすべてのフィールド( _idを除く)の値をインデックス化するには、インデックスキーとして"$**"を指定します。

db.collection.createIndex( { "$**" : 1 } )

このワイルドカード インデックスを使用すると、MongoDB はコレクション内の核ドキュメントのすべてのフィールドにインデックスを作成します。 特定のフィールドがネストされたドキュメントまたは配列の場合、ワイルドカード インデックスはドキュメントまたは配列に再帰し、ドキュメントまたは配列内のすべてのフィールドの値を保存します。

例については、「すべてのフィールドパスでのワイルドカード インデックスの作成 」を参照してください。

注意

ワイルドカード インデックスでは、デフォルトで_idフィールドが省略されます。 ワイルドカード インデックスに_idフィールドを含めるには、 wildcardProjectionドキュメントに明示的に含める必要があります。 詳細については、 wildcardインデックスのオプション を参照してください。

ドキュメント内の複数の特定のフィールドの値をインデックス化するには:

db.collection.createIndex(
{ "$**" : 1 },
{ "wildcardProjection" :
{ "fieldA" : 1, "fieldB.fieldC" : 1 }
}
)

このワイルドカード インデックスを使用すると、MongoDB はコレクション内の各ドキュメントの指定されたフィールドのすべての値をインデックス化します。 特定のフィールドがネストされたドキュメントまたは配列の場合、ワイルドカード インデックスはドキュメントまたは配列に再帰し、ドキュメントまたは配列内のすべてのフィールドの値を保存します。

注意

ワイルドカード インデックスは、 _idフィールドを明示的に含める場合を 除きwildcardProjectionドキュメントに包含・除外ステートメントを混在させることはできません。 wildcardProjectionの詳細についてはwildcardインデックスのオプション を参照してください。

例については、「ワイルドカード インデックスのカバレッジに特定のフィールドを含める 」を参照してください。

特定のフィールドパスを除くドキュメント内のすべてのフィールドのフィールドにインデックスを付けるには

db.collection.createIndex(
{ "$**" : 1 },
{ "wildcardProjection" :
{ "fieldA" : 0, "fieldB.fieldC" : 0 }
}
)

このワイルドカード インデックスを使用すると、MongoDB は指定されたフィールドパスを除くコレクション内の各ドキュメントのすべてのフィールドにインデックスを作成します。 特定のフィールドがネストされたドキュメントまたは配列の場合、ワイルドカード インデックスはドキュメントまたは配列に再帰し、ドキュメントまたは配列内のすべてのフィールドの値を保存します。

例については、「ワイルドカード インデックスのカバレッジから特定のフィールドを除外する 」を参照してください。

注意

ワイルドカード インデックスは、 _idフィールドを明示的に含める場合を 除きwildcardProjectionドキュメントに包含・除外ステートメントを混在させることはできません。 wildcardProjectionの詳細についてはwildcardインデックスのオプション を参照してください。

MongoDB5.0以降、ワイルドカード インデックスは作成後に正規化されます。ワイルドカード プロジェクション フィールドが同等のフィルターを しない限り、同じExpress キー パターン を使用して複数のワイルドカード インデックスを作成できます。

たとえば、ワイルドカード インデックスを作成します。

db.books.createIndex( { "$**" : 1 }, { wildcardProjection : {a: 1, "b.c": 1 } } )

db.collection.getIndexes()メソッドでインデックスを表示する。

db.books.getIndexes()

結果は、正規化された形式で表示されます。

{ v: 2, key: { _id: 1 }, name: '_id_' },
{
v: 2,
key: { '$**': 1 },
name: '$**_1',
wildcardProjection: { a: true, b: { c: true }, _id: false }
}
  • ワイルドカード インデックスは、任意のクエリ述語で最大1 つのフィールドをサポートできます。 ワイルドカード インデックス クエリのサポートの詳細については、 ワイルドカード インデックス クエリとソートのサポート を参照してください。

  • ワイルドカード インデックスを作成するには、 mongod featureCompatibilityVersion4.2である必要があります。 fCV を設定する手順については、「 MongoDB 5.0 配置で機能の互換性バージョンを設定する 」を参照してください。

  • ワイルドカード インデックスでは、デフォルトで _id フィールドが省略されます。 _idフィールドをワイルドカード インデックスに含めるには、ワイルドカード プロジェクション ドキュメントに明示的に含める必要があります( { "_id" : 1 } )。

  • コレクション内に複数のワイルドカード インデックスを作成できます。

  • ワイルドカード インデックスは、コレクション内の他のインデックスと同じフィールドをカバーする場合があります。

  • ワイルド インデックスはスパース インデックスであるため、インデックス フィールドに null 値が含まれていても、インデックス フィールドを持つドキュメントのエントリのみが含まれます。

ワイルドカード インデックスは、オブジェクト(埋め込みドキュメント)または配列であるフィールドをインデックス化する場合、特定の動作をします。

  • フィールドがオブジェクトの場合、ワイルドカード インデックスはオブジェクトに降順を返し、その内容にインデックスを作成します。 ワイルドカード インデックスは、検出された追加の埋め込みドキュメントに降順を続行します。

  • フィールドが配列の場合、ワイルドカード インデックスは配列を走査し、各要素にインデックスを作成します。

    • 配列内の要素がオブジェクトの場合、ワイルドカード インデックスはオブジェクトに下降して、上記で説明したようにその内容にインデックスを作成します。

    • 要素が配列、つまり親配列に直接埋め込まれている配列の場合、ワイルドカード インデックスは埋め込まれた配列をトラバースせ、配列全体を単一の値としてインデックス化します。

  • 他のすべてのフィールドについては、プリミティブ(オブジェクトまたは配列)値をインデックスに記録します。

ワイルドカード インデックスは、プリミティブ値(オブジェクトまたは配列ではないフィールド)に達するまで、追加のネストされたオブジェクトまたは配列をトラバースします。 次に、このプリミティブ値とそのフィールドへのフルパスのインデックスを作成します。

たとえば、次のドキュメントについて考えてみます。

{
"parentField" : {
"nestedField" : "nestedValue",
"nestedObject" : {
"deeplyNestedField" : "deeplyNestedValue"
},
"nestedArray" : [
"nestedArrayElementOne",
[ "nestedArrayElementTwo" ]
]
}
}

parentFieldを含むワイルドカード インデックスは次のエントリを記録します。

  • "parentField.nestedField" : "nestedValue"

  • "parentField.nestedObject.deeplyNestedField" : "deeplyNestedValue"

  • "parentField.nestedArray" : "nestedArrayElementOne"

  • "parentField.nestedArray" : ["nestedArrayElementTwo"]

parentField.nestedArrayのレコードには各要素の配列位置が含まれていないことに注意してください。 ワイルドカード インデックスは、要素をインデックスに記録するときに、配列要素の位置を無視します。 ワイルドカード インデックスは、明示的な配列インデックスを含むクエリを引き続きサポートできます。 詳細については、「明示的な配列インデックスを含むクエリ」を参照してください。

ネストされたオブジェクトでのワイルドカード インデックスの動作の詳細については、「ネストされたオブジェクト 」を参照してください。

ネストされた配列でのワイルドカード インデックスの動作の詳細については、「ネストされた配列 」を参照してください。

ワイルドカード インデックスはネストされたオブジェクトを検出すると、そのオブジェクトに降順を返し、その内容をインデックス化します。 例:

{
"parentField" : {
"nestedField" : "nestedValue",
"nestedArray" : ["nestedElement"]
"nestedObject" : {
"deeplyNestedField" : "deeplyNestedValue"
}
}
}

parentFieldを含むワイルドカード インデックスは、 オブジェクトに下降して、その内容を走査してインデックスを作成します。

  • それ自体がオブジェクト(つまり、埋め込みドキュメント)である各フィールドについては、 オブジェクトに下降してその内容をインデックス化します。

  • 配列である各フィールドについて、配列を走査し、その内容をインデックス化します。

  • 他のすべてのフィールドについては、プリミティブ(オブジェクトまたは配列)値をインデックスに記録します。

ワイルドカード インデックスは、プリミティブ値(オブジェクトまたは配列ではないフィールド)に達するまで、追加のネストされたオブジェクトまたは配列をトラバースします。 次に、このプリミティブ値とそのフィールドへのフルパスのインデックスを作成します。

サンプル ドキュメントの場合、ワイルドカード インデックスは次のレコードをインデックスに追加します。

  • "parentField.nestedField" : "nestedValue"

  • "parentField.nestedObject.deeplyNestedField" : "deeplyNestedValue"

  • "parentField.nestedArray" : "nestedElement"

ネストされた配列でのワイルドカード インデックスの動作の詳細については、「ネストされた配列 」を参照してください。

ワイルドカード インデックスがネストされた配列を検出すると、その配列を走査してその要素にインデックスを作成しようとします。 配列が親配列(埋め込み配列)の要素である場合、ワイルドカード インデックスはその内容を走査せず、代わりに配列全体を値として記録します。 例:

{
"parentArray" : [
"arrayElementOne",
[ "embeddedArrayElement" ],
"nestedObject" : {
"nestedArray" : [
"nestedArrayElementOne",
"nestedArrayElementTwo"
]
}
]
}

parentArrayを含むワイルドカード インデックスは、 配列に下降して、その内容を走査してインデックスを作成します。

  • 配列である各要素(つまり、埋め込み配列)について、配列全体を値としてインデックスします。

  • オブジェクトである各要素については、 オブジェクトに下降してその内容を走査し、インデックスを作成します。

  • 他のすべてのフィールドについては、プリミティブ(オブジェクトまたは配列)値をインデックスに記録します。

ワイルドカード インデックスは、プリミティブ値(オブジェクトまたは配列ではないフィールド)に達するまで、追加のネストされたオブジェクトまたは配列をトラバースします。 次に、このプリミティブ値とそのフィールドへのフルパスのインデックスを作成します。

サンプル ドキュメントの場合、ワイルドカード インデックスは次のレコードをインデックスに追加します。

  • "parentArray" : "arrayElementOne"

  • "parentArray" : ["embeddedArrayElement"]

  • "parentArray.nestedObject.nestedArray" : "nestedArrayElementOne"

  • "parentArray.nestedObject.nestedArray" : "nestedArrayElementTwo"

parentField.nestedArrayのレコードには各要素の配列位置が含まれていないことに注意してください。 ワイルドカード インデックスは、要素をインデックスに記録するときに、配列要素の位置を無視します。 ワイルドカード インデックスは、明示的な配列インデックスを含むクエリを引き続きサポートできます。 詳細については、「明示的な配列インデックスを含むクエリ」を参照してください。

Tip

以下も参照してください。

MongoDB 5.0.16以降、 wildcardProjectionフィールドにはインデックスプロジェクションが送信された形式で保存されます。 それ以前のバージョンでは、プロジェクションは正規化された形式で保存されている場合があります。

サーバーは同じ方法でインデックスを使用しますが、 listIndexes } コマンドとdb.collection.getIndexes()コマンドの出力には違いが生じる場合があります。

  • ワイルドカード インデックスを使用してコレクションをシャーディングすることはできません。 シャーディングしたいフィールドに非ワイルドカード インデックスを作成します。 シャードキー選択の詳細については、「シャードキー 」を参照してください。

  • 複合インデックスは作成できません。

  • ワイルドカード インデックスに次のプロパティを指定することはできません。

  • ワイルドカード構文を使用して次のインデックス タイプは作成できません。

重要

ワイルドカード インデックスは、ワイルドカード テキスト インデックスとは区別され、互換性もありません。ワイルドカード インデックスは $text 演算子を使用するクエリをサポートしていません。

ワイルドカード インデックス作成の制限に関する詳細なドキュメントについては、「互換性のないインデックス タイプまたはプロパティ 」を参照してください。

ワイルドカード インデックスは、次のすべてが当てはまる 場合にのみ 、 カバード クエリ をサポートできます。

  • クエリ プランナーが、クエリ述語を満たすワイルドカード インデックスを選択する

  • クエリ述語が、ワイルドカード インデックスの対象となるフィールドを 1 つだけ指定している

  • プロジェクションは、 _idを明示的に除外し、クエリ フィールドのみを含めます。

  • 指定されたクエリ フィールドは配列ではない

employees コレクションの次のワイルドカード インデックスを検討します。

db.products.createIndex( { "$**" : 1 } )

次の操作では、1 つのフィールド lastName をクエリし、結果のドキュメントから他のすべてのフィールドをプロジェクトします。

db.products.find(
{ "lastName" : "Doe" },
{ "_id" : 0, "lastName" : 1 }
)

指定されたlastNameが配列ではないことを前提とすると、MongoDB はカバード クエリをサポートするために$**ワイルドカード インデックスを使用できます。

ワイルドカード インデックスは、最大1 つのクエリ述語フィールドをサポートできます。 つまり、

  • MongoDB では、非ワイルドカード インデックスを使用してクエリ述語の 1 つの部分を満たすことができず、ワイルドカードを使用して別の部分を満たすことはできません。

  • MongoDB では、クエリ述語の一部を満たすために 1 つのワイルドカード インデックスを使用し、別の部分を満たすために別のワイルドカード インデックスを使用することはできません。

  • 1 つのワイルドカード インデックスが複数のクエリ フィールドをサポートできる場合でも、MongoDB はワイルドカード インデックスを使用してクエリ フィールドの 1 つだけをサポートできます。 残りのすべてのフィールドは、インデックスなしで解決されます。

ただし、MongoDB では、クエリ$orまたは集計$or演算子の各独立した引数を満たすために同じワイルドカード インデックスが使用される場合があります。

MongoDB では、次のすべてが当てはまる 場合にのみsort() 、 を満たすためにワイルドカード インデックスを使用できます。

  • クエリ プランナーが、クエリ述語を満たすワイルドカード インデックスを選択する

  • sort()はクエリ述語フィールドのみを指定します。

  • 指定されたフィールドは配列ではない

上記の条件が満たされない場合、MongoDB はソートにワイルドカード インデックスを使用できません。 MongoDB は、クエリ述語とは異なるインデックスを必要とするsort()操作をサポートしていません。 詳細については、「インデックスの交差とソート 」を参照してください。

products コレクションの次のワイルドカード インデックスを検討します。

db.products.createIndex( { "product_attributes.$**" : 1 } )

次の操作では、単一のフィールドproduct_attributes.priceをクエリし、その同じフィールドでソートします。

db.products.find(
{ "product_attributes.price" : { $gt : 10.00 } },
).sort(
{ "product_attributes.price" : 1 }
)

指定されたpriceが配列ではないことを前提とすると、MongoDB はproduct_attributes.$**ワイルドカード インデックスを使用してfind()sort()の両方を満たすことができます。

ワイルドカード インデックスは次のクエリ パターンをサポートしていません

  • フィールドが存在しないかどうかを確認するクエリ

  • フィールドがドキュメントまたは配列と等しいかどうかを確認するクエリ

  • フィールドが null と等しいかどうかを確認するクエリ

詳細については、「サポートされていないクエリと集計パターン 」を参照してください。

MongoDB ワイルドカード インデックスでは、インデックス作成中に配列内の特定の要素の配列位置は記録されません。 ただし、MongoDB では、1 つ以上の明示的な配列インデックスを持つフィールドパスを含むクエリに応答するためにワイルドカード インデックスを選択することもできます(たとえば、 parentArray.0.nestedArray.0 )。 連続するネストされた配列ごとにインデックスの限界を定義する複雑さのため、MongoDB は、そのパスに8個を超える明示的な配列インデックスが含まれている場合、クエリ内の特定のフィールドパスにクエリを実行するためにワイルドカード インデックスを考慮しません。 MongoDB では、クエリ内の他のフィールドパスに応答するために、ワイルドカード インデックスを使用することも検討できます。

以下に例を挙げます。

{
"parentObject" : {
"nestedArray" : [
"elementOne",
{
"deeplyNestedArray" : [ "elementTwo" ]
}
]
}
}

MongoDB では、次のクエリを満たすためにparentObjectを含むワイルドカード インデックスを選択できます。

  • "parentObject.nestedArray.0" : "elementOne"

  • "parentObject.nestedArray.1.deeplyNestedArray.0" : "elementTwo"

クエリ述語内の特定のフィールドパスで 8 個を超える明示的な配列インデックスが指定されている場合、MongoDB は、そのフィールドパスを応答するためにワイルドカード インデックスを考慮しません。 MongoDB は、クエリに答えるために別の適格なインデックスを選択する、コレクションスキャンを実行します。

ワイルドカード インデックス自体には、インデックス作成中にドキュメントを走査する深度に制限がないことに注意してください。この制限は、配列インデックスを明示的に指定するクエリにのみ適用されます。 明示的な配列インデックスなしで同じクエリを発行すると、MongoDB はクエリに答えるために ワイルドカード インデックス を選択する場合があります。

  • "parentObject.nestedArray" : "elementOne"

  • "parentObject.nestedArray.deeplyNestedArray" : "elementTwo"

Tip

以下も参照してください。

戻る

マルチキー インデックスの限界