ユニークインデックスにより、インデックス フィールドに重複する値が保存されなくなり、特定のフィールドに値が最大 1 回表示されるようになります。一意の複合インデックスを使用すると、インデックスキー値の任意の組み合わせが最大 1 回だけ表示されます。デフォルトでは、 MongoDB はコレクションの作成 中に _idフィールドにユニークインデックスを作成します。
でホストされる配置用MongoDB Atlas に、 一意のインデックスを UI に作成して管理 できます 。
ユニークインデックスの作成
ユニークインデックスを作成するには、unique オプションを true に設定した状態で、db.collection.createIndex() メソッドを使用します。
db.collection.createIndex( <key and index type specification>, { unique: true } )
単一フィールドのユニークインデックス
たとえば、 usersコレクションのemailフィールドに一意のインデックスを作成するには、 mongoshで次の操作を使用します。
db.users.createIndex( { "email": 1 }, { unique: true } )
ユニーク複合インデックス
複合インデックスにも一意の制約を適用できます。 一意の複合インデックスでは、インデックス キー値の組み合わせに一意であることが強制されます。
たとえば、 usersコレクションのname 、 email 、およびpasswordフィールドに一意のインデックスを作成するには、 mongoshで次の操作を使用します。
db.users.createIndex( { name: 1, email: 1, password: 1 }, { unique: true } )
作成されたインデックスでは、name、email、password の値の組み合わせは必然的に一意になります。
次のとおり、ユニークな複合マルチキー インデックスを email と name に作成します。
db.users.createIndex( { "email": 1, "name": 1 }, { unique: true } )
ユニークインデックスを使用すると、email と name の値の 組み合わせが必然的に一意になるため、次のドキュメントをコレクションに挿入できます。
db.users.insertMany( [ { name: "Catelyn Stark", email: [ "catelyn@gameofthron.es", "sean_bean@gameofthron.es" ], password: "$2b$12$hash2" }, { name: "Arya Stark", email: [ "catelyn@gameofthron.es" ], password: "$2b$12$hash3" } ] )
両方のドキュメントで"catelyn@gameofthron.es" email配列に が含まれていても、 フィールドと各メール値の組み合わせは一意であるため、操作は成功します。name
動作
制限事項
MongoDBは、コレクションにユニーク制約に違反するデータが既に含まれている場合、指定されたインデックス フィールドにユニークインデックスを作成できません。
ハッシュされたインデックスにユニーク制約を指定することはできません。
レプリカセットとシャーディングされたクラスターでのユニークインデックスの構築
レプリカセットとシャーディングされたクラスターでローリング手順を使用してユニークインデックスを作成するには、その手順の実行中にコレクションへの書込みをすべて停止する必要があります。書込みを停止できない場合は、ローリング手順は使用せず、代わりに、次のいずれかの方法でコレクションにユニークインデックスを構築します。
レプリカセットのプライマリで
db.collection.createIndex()を発行する。シャーディングされたクラスター向けに
mongosに対してdb.collection.createIndex()を発行する。
個別ドキュメント間でのユニーク制約
ユニーク制約は、コレクション内のドキュメントに個別に適用されます。具体的には、個別のドキュメントでインデックス キーの値が同じになることはありません。
この制約は個別のドキュメントに適用されるため、ユニークマルチキー インデックスの場合、ドキュメントに含まれる配列要素によって、そのドキュメントのインデックス キー値と別のドキュメントのインデックス キー値が重複していない限り、インデックス キー値の反復につながることがあります。この場合、反復されるインデックスエントリはインデックスに 1 度のみ挿入されます。
例、email と name に一意の複合マルチキーインデックスを作成します。
db.users.createIndex( { "email": 1, "name": 1 }, { unique: true } )
ユニークインデックスを使用すると、インデックスキー値が { "email": "arya@winterfell.com", "name": null } であるドキュメントが他にない場合は、次のドキュメントをコレクションに挿入できます。
db.users.insertOne( { _id: ObjectId("59b99db4cfa9a34dcd7885b9"), email: [ "arya@winterfell.com", "arya@gameofthron.es" ] } )
ユニークな単一フィールド インデックス内でのドキュメント フィールドの欠落
ドキュメントの単一フィールドのユニークインデックスのインデックス フィールドに null または欠損値がある場合、インデックスはそのドキュメントに null 値を保存します。単一フィールドのユニークインデックスはユニーク制約により、インデックスエントリに null 値を含むドキュメントを 1 つしか含めることができません。インデックスエントリに null 値があるドキュメントが複数ある場合、インデックス構築は重複キーエラーで失敗します。
email にユニークな単一フィールド インデックスがあるコレクションを例にしましょう。
db.users.createIndex( { "email": 1 }, { unique: true } )
ユニークインデックスを使用しているため、email フィールドのないドキュメントがコレクションに既にない場合は、email フィールドがなくてもドキュメントを挿入できます。
db.users.insertOne( { name: "Arya Stark" } )
ただし、フィールドpassword のないドキュメントがコレクションにすでに含まれている場合は、フィールドemail がないと 2 番目のドキュメントを挿入できません。 emailフィールドなしで別のドキュメントを挿入しようとする 2 番目の操作は、emailフィールドの一意の制約に違反しているため、失敗します。
ユニーク部分インデックス
部分インデックスは、指定されたフィルター式を満たすコレクション内のドキュメントのみをインデックスします。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.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" } )
キー パターンが重複する基本インデックスとユニークインデックス
MongoDB 5.0 以降、基本インデックスとユニークインデックスは同じキー パターンで共存できます。
重複するキー パターンが認められるため、インデックスを作成済みのフィールドにユニークインデックスを追加できます。
例では、同じキー パターンを使用する次の両方のインデックスを作成できます。
db.users.createIndex( { email : 1 }, { name: "basic_index" } )
db.users.createIndex( { email : 1 }, { name: "unique_index", unique: true } )