一意なインデックス により、インデックス フィールドの値が一意になります。
一意の単一フィールドインデックスを使用すると、特定のフィールドに値が最大 1 回表示されるようになります。
一意の複合インデックスを使用すると、インデックスキー値の任意の組み合わせが最大 1 回だけ表示されます。
デフォルトでは 、 MongoDB は新しいコレクションを作成するときに、 _idフィールドにユニークインデックスを作成します。
でホストされる配置用MongoDB Atlas に、 一意のインデックスを UI に作成して管理 できます 。
MongoDB Shell でユニークインデックスを作成するには、 オプションをdb.collection.createIndex() uniqueに設定して、true メソッドを使用します。
db.collection.createIndex( { <field>: <sortOrder> }, { unique: true } )
はじめる
ユニークインデックスを作成するには、以下を参照してください。
詳細
preserveUnique オプション
MongoDB、コレクションに一意の制約に違反するデータがすでに含まれている場合、ユニークインデックスを直接作成できません。重複する値を含むコレクションにユニークインデックスを作成するには、prepareUnique オプションを使用できます。
重複する値を含むコレクションで prepareUnique を使用するには、次の手順に従います。
一意性を強制したいフィールドに、ユニークインデックスを作成します。
コマンドを使用して、インデックスの
collModprepareUniqueを に設定します。trueprepareUniqueをtrueに設定すると、インデックスフィールドへのすべての新しい書込みに対して一意の制約が適用されます。既存の重複値は削除されません。インデックスフィールド内の既存の重複値を解決します。
インデックスを一意にするには、
collModコマンドを使用します。
prepareUnique 機能は、重複を解除したい重複値を含むデータセットがすでに存在し、クリーンアップ プロセス中に新しい重複値が追加されないようにする必要がある場合に便利です。
を使用する完全な例については、「prepareUnique 既存のインデックスを一意のインデックスに変換する 」を参照してください。
レプリカセットとシャーディングされたクラスターでのユニークインデックスの構築
レプリカセットとシャーディングされたクラスターでローリング手順を使用してユニークインデックスを作成するには、その手順の実行中にコレクションへの書込みをすべて停止する必要があります。書込みを停止できない場合は、ローリング手順は使用せず、代わりに、次のいずれかを行ってコレクションにユニークインデックスを構築する必要があります。
レプリカセットのプライマリで
db.collection.createIndex()を実行するシャーディングされたクラスターの
mongosでdb.collection.createIndex()を実行
配列フィールドに対する一意の制約
ユニーク制約は、コレクション内のドキュメントに個別に適用されます。具体的には、個別のドキュメントでインデックス キーの値が同じになることはありません。
この制約は個別のドキュメントに適用されるため、ユニークマルチキー インデックスの場合、ドキュメントに含まれる配列要素によって、そのドキュメントのインデックス キー値と別のドキュメントのインデックス キー値が重複していない限り、インデックス キー値の反復につながることがあります。この場合、反復されるインデックスエントリはインデックスに 1 度のみ挿入されます。
例、製品とその在庫場所を表す次のドキュメントを含む inventoryコレクションを考えてみましょう。
db.inventory.insertMany( [ { _id: 1, product: "pencils", inventory: [ { warehouse: "NYC", quantity: 5 }, { quantity: 10 } ] }, { _id: 2, product: "pens", inventory: [ { warehouse: "NYC" }, { quantity: 5 } ] }, { _id: 3, product: "markers", inventory: [ { warehouse: "NYC", quantity: 10 } ] } ] )
次のとおり、ユニーク複合マルチキー インデックスを inventory.warehouse と inventory.quantity に作成します。
db.products.createIndex( { "inventory.warehouse": 1, "inventory.quantity": 1 }, { unique: true } )
ユニークインデックスを使用すると、インデックスキー値が { "inventory.warehouse": "LA", "inventory.quantity": null } であるドキュメントが他にない場合は、次のドキュメントをコレクションに挿入できます。
db.products.insertOne( { _id: 4, product: "Sprocket", inventory: [ { warehouse: "LA" }, { warehouse: "LA" } ] } )
ユニークな単一フィールド インデックス内でのドキュメント フィールドの欠落
ドキュメントの単一フィールドのユニークインデックスのインデックス フィールドに null または欠損値がある場合、インデックスはそのドキュメントに null 値を保存します。単一フィールドのユニークインデックスはユニーク制約により、インデックスエントリに null 値を含むドキュメントを 1 つしか含めることができません。インデックスエントリに null 値があるドキュメントが複数ある場合、インデックス構築は重複キーエラーで失敗します。
x にユニークな単一フィールド インデックスがあるコレクションを例にしましょう。
db.collection.createIndex( { "x": 1 }, { unique: true } )
ユニークインデックスを使用しているため、x フィールドのないドキュメントがコレクションに既にない場合は、x フィールドがなくてもドキュメントを挿入できます。
db.collection.insertOne( { y: 1 } )
ただし、x フィールドのないドキュメントがコレクションに既に含まれている場合は、x フィールドがないとドキュメントを挿入できません。
db.collection.insertOne( { z: 1 } )
x フィールドの値に課されているユニーク制約に違反しているため、ドキュメントの挿入操作は失敗します。
WriteResult({ "nInserted" : 0, "writeError" : { "code" : 11000, "errmsg" : "E11000 duplicate key error index: test.collection.$a.b_1 dup key: { : null }" } })
ユニーク複合インデックス内でのドキュメント フィールドの欠落
ドキュメントの複合ユニークインデックスの 1 つ以上のインデックス フィールドにnull または欠落値がある場合、インデックスは、ドキュメントのインデックスエントリ内の各 null または欠落フィールドに null 値を保存します。複合ユニークインデックスではユニーク制約により、複合ユニークインデックスでインデックスエントリ内のインデックス フィールドに null 値を含めることができるドキュメントは 1 つに限定されます。インデックス フィールドに null 値があるインデックスエントリが複数ある場合、インデックス構築は重複キーエラーで失敗します。MongoDB は、各インデックスエントリが一意である限り、複合ユニークインデックスに欠落フィールドがあるドキュメントを複数許容します。
たとえば、コレクション students の name、age、grade の各フィールドに一ユニーク複合インデックスがあるとします。
db.students.createIndex( { "name": 1, "age": -1, "grade": 1 }, { unique: true } )
コレクションに既存の同一ドキュメントがない場合、ユニーク複合インデックスでは、grade フィールドがすべて欠落している次のドキュメントを挿入することができます。
db.students.insertMany( [ { "name": "Meredith", "age": 12 }, { "name": "Olivia", "age": 11 }, { "name": "Benjamin" } ] )
ただし、インデックスキー(name、age、grade の値)がコレクション内の別のドキュメントと同じであるドキュメントは挿入できません。
db.students.insertOne( { name: "Meredith", age: 12 } )
name、age、grade の各フィールドの値に課されている一意という制約に違反しているため、ドキュメントの挿入操作は失敗します。
WriteResult({ "nInserted" : 0, "writeError" : { "code" : 11000, "errmsg" : "E11000 duplicate key error collection: test.students index: name_1_age_-1_grade_1 dup key: { name: "Meredith", age: 12, grade: null } } } )
また、一意であっても既存のインデックスエントリとインデックスキーを共有するドキュメントは挿入できません。
db.students.insertOne( { name: "Olivia", "age": 11, "favorite color": "red"} )
name、age、grade の各フィールドの値に課されている一意という制約に違反しているため、ドキュメントの挿入操作は失敗します。
WriteResult({ "nInserted" : 0, "writeError" : { "code" : 11000, "errmsg" : "E11000 duplicate key error collection: test.students index: name_1_age_-1_grade_1 dup key: { name: "Olivia", age: 11, grade: null } } } )
ユニーク部分インデックス
部分インデックスは、指定された フィルター式 を満たすコレクション内のドキュメントのみをインデックス。 partialFilterExpression とユニーク制約の両方を指定した場合、ユニーク制約はフィルター式 を満たすドキュメントにのみ適用されます。
部分インデックスでユニーク制約を指定しても、ドキュメントがフィルタリング条件を満たさない場合は、当該ユニーク制約を満たさないドキュメントも挿入されます。例については、「ユニーク制約を持つ部分インデックス」を参照してください。
シャーディングされたクラスターとユニークインデックス
ハッシュされたインデックスにユニーク制約を指定することはできません。
範囲ベースのシャーディングされたコレクションでは、次のインデックスのみが一意である可能性があります。
シャードキーのインデックス。
シャードキーが プレフィックス である複合インデックス。
_idデフォルトの インデックス。ただし、_idインデックスは、_idフィールドがシャードキーでない場合にのみ、シャードごとに一意の制約を強制します。
重要
_id フィールドがシャードキーでない場合、シャードクラスターはクラスター全体で _id フィールドの一意性の制約を強制しません。
_idフィールドがシャードキーでない場合、一意制約はドキュメント を保存するシャードにのみ適用されます。つまり、異なるシャードで発生する場合には、2 つ以上のドキュメントが同じ _id 値を持つことができます。
例、2 つのシャード A と B にまたがるシャードキー{x:
1} を持つシャーディングされたコレクションを考えてみましょう。_id キーはシャードキーではないため、コレクションにはシャード A に _id 値 1 を持つドキュメントがある可能性があります。 、およびシャード B に _id 値 1 を持つ別のドキュメントが含まれている。
_idフィールドがシャードキーでない場合、 MongoDB、アプリケーションが _idフィールドに一意の識別子を使用して入力することで、シャード全体で _id 値の一意性を確保することを想定しています(例: ) 。
ユニークインデックスの制約とは、次のことを意味します。
シャーディングされたコレクションの場合、コレクションに複数の一意なインデックスがある場合、シャードキーはすべての一意なインデックスのプレフィックスではない限り、コレクションをシャードできません。
すでにシャーディングされたコレクションの場合、シャードキーがプレフィックスとして含まれていない限り、他のフィールドに一意なインデックスを作成することはできません。
ユニークインデックスは、インデックスフィールドがないドキュメントの null 値を保存します。つまり、インデックスフィールドがない場合は、
nullインデックスキー値の別のインスタンスとして扱われます。 詳細については、「 一意の単一フィールドインデックスにドキュメントフィールドがない場合 」を参照してください。
シャードキーではないフィールドの一意性を維持するには、「任意のフィールドに対する一意の制約 」を参照してください。
ユニークスパース/非スパースインデックス
MongoDB 5.0 以降、キー パターンが同じユニークスパースおよびユニーク非スパースインデックスを単一コレクションに混在させることができます。
ユニークおよびスパースインデックスの作成
次の例では、キー パターンが同じで sparse オプションが異なる複数のインデックスを作成します。
db.scoreHistory.createIndex( { score : 1 }, { name: "unique_index", unique: true } ) db.scoreHistory.createIndex( { score : 1 }, { name: "unique_sparse_index", unique: true, sparse: true } )
基本インデックスとスパースインデックスの作成
スパース オプションの有無にかかわらず、同じキー パターンで基本インデックスを作成することもできます。
db.scoreHistory.createIndex( { score : 1 }, { name: "sparse_index", sparse: true } ) db.scoreHistory.createIndex( { score : 1 }, { name: "basic_index" } )
キー パターンが重複する基本インデックスとユニークインデックス
基本インデックスと一意のインデックスは、同じキー パターンを持つ存在できます。
重複するキー パターンが認められるため、インデックスを作成済みのフィールドにユニークインデックスを追加できます。
この例では、次のことが行われます。
キー パターン { score : 1 } を使用して基本インデックスを作成し、3 つのドキュメントを挿入します。
db.scoreHistory.createIndex( { score : 1 }, { name: "basic_index" } ) db.scoreHistory.insert( { score : 1 } ) db.scoreHistory.insert( { score : 2 } ) db.scoreHistory.insert( { score : 3 } )
同じキーパターン { score : 1 } を持つユニークインデックスを作成します。
db.scoreHistory.createIndex( { score : 1 }, { name: "unique_index", unique: true } )
score が重複するドキュメントの挿入を試みても、ユニークインデックスであるため失敗します。
db.scoreHistory.insert( { score : 3 } )