MongoDB で unique 制約を適用する方法
今回は「MongoDB で unique 制約を適用する方法」について見てみよう。
unique 制約の適用
MongoDB で unique 制約を適用するには、インデックスを作成するときに createIndex() のオプションとして unique に true を指定すればよい。
以下では、「単一キーインデックス」の場合と「複合キーインデックス」の場合について、サンプルコードを見ていく。
単一キーインデックス
単一キーインデックスであれば、単純に次のようなコードを mongo シェルで実行すると作成できる。
> db.members.createIndex({ userId: 1 }, { unique: true })
複合キーインデックス
複合キーインデックスの場合も、単一キーインデックスとコードは変わらない。
> db.members.createIndex({ firstname: 1, lastname: 1 }, { unique: true })
複合キーインデックスの場合、複合キーの組み合わせとして一意であればよいため、以下は問題なく設定できる。
> db.members.insert({ firstname: "kc", lastname: "Kim" })
> db.members.insert({ firstname: "et", lastname: "Kim" })
> db.members.insert({ firstname: "kc" })
unique 制約の設定制限
RDB の場合と似ているが、すでに重複データが登録されているコレクションに対して unique 制約を設定することはできない。すでに重複している状態では当然と言えば当然である。
また、ハッシュインデックスに対して unique 制約を設定することは推奨されない。(Hashed Indexes の Considerations)
unique 制約キーに値が設定されていない場合の動作
上で「複合キーインデックス」に unique 制約を設定したデータ登録例のように、値がないフィールドが存在する場合、内部的には null が指定されたものとして処理される。
たとえば、次のようにフィールド x に対する unique 制約があるコレクションがあるとする。
> db.collection.createIndex({ x: 1 }, { unique: true })
フィールド x を指定しないデータが登録されたと仮定する。
> db.collection.insert({ y: 1 })
WriteResult({ "nInserted" : 1 })
最初は x: null として指定されるため、正常に登録できる。続けて、フィールド x が存在しない別のデータを挿入するとどうなるだろうか。
> db.collection.insert({ z: 1 })
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: test.collection index: x_1 dup key: { : null }"
}
})
上記のようにエラーが発生し、挿入できないことがわかる。また、エラーメッセージからも、指定がない場合は null が指定されることがわかる。