この記事では、ドキュメントのフィールド値の一意性を確保するために使用できる MongoDB の一意のインデックスを紹介します。
一意のインデックス
多くの場合、電子メールやユーザー名など、ドキュメント内のフィールド値の一意性を確認する必要があります。このようなビジネス ルールの実装に役立つのが、一意のインデックス (一意のインデックス) です。実際、MongoDB は一意のインデックスを使用して主キー _id の一意性を保証します。
一意のインデックスを作成する方法は通常のインデックスの作成方法と同じですが、追加で指定する必要があるのは {unique: true} オプションのみです。
db.collection.createIndex({
field: 1}, {
unique: true});
インデックスの例
まず、新しいコレクション users を作成し、いくつかのドキュメントを挿入します。
db.users.insertMany([
{
name: "张三", dob: "1990-01-01", email: "[email protected]"},
{
name: "李四", dob: "1992-06-30", email: "[email protected]"}
]);
次に、電子メール フィールドに基づいて一意のインデックスを作成します。
db.users.createIndex({
email:1},{
unique:true});
次に、既存のドキュメントを挿入してみます。
db.users.insertOne(
{
name: "张叁", dob: "1995-03-12", email: "[email protected]"}
);
この時点で、MongoDB は次のエラーを返します。
MongoServerError: E11000 duplicate key error collection: book.users index: email_1 dup key: {
email: '[email protected]' }
コレクション内に重複データがすでに存在する場合に一意のインデックスを作成する方法を示します。まずコレクション ユーザーを削除して再構築します。
db.users.drop()
db.users.insertMany([
{
name: "张三", dob: "1990-01-01", email: "[email protected]"},
{
name: "张叁", dob: "1995-03-12", email: "[email protected]"},
{
name: "李四", dob: "1992-06-30", email: "[email protected]"}
]);
次に、電子メール フィールドに基づいて一意のインデックスを作成します。
db.users.createIndex({
email: 1},{
unique:true})
MongoServerError: Index build failed: 95f78956-d5d0-4882-bfe0-2d856df18c61: Collection book.users ( 6da472db-2884-4608-98b6-95a003b4f29c ) :: caused by :: E11000 duplicate key error collection: mflix.users index: email_1 dup key: {
email: zhangsan@test.com }
上記のエラーの原因は、電子メール内に重複したレコードがあることです。
通常、データを挿入する前に一意のインデックスを作成します。これにより、データの一意性を最初から確保できます。既存のデータに基づいて一意のインデックスを作成する場合、データの重複によりインデックスの作成が失敗する可能性があります。これを行うには、インデックスを作成する前に重複データを削除する必要があります。
たとえば、最初に重複ユーザーを削除できます。
db.users.deleteOne({
name: "张叁", dob: "1995-03-12", email: "[email protected]"});
{
acknowledged: true, deletedCount: 1 }
次に、電子メール フィールドに基づいて一意のインデックスを作成します。
db.users.createIndex({
email: 1},{
unique:true})
email_1
複合一意のインデックス
複数のフィールドに基づく一意のインデックスは、一意の複合インデックスです。複合一意インデックスにより、複数のフィールド値の組み合わせが一意であることが保証されます。たとえば、フィールド field1 と field2 に基づいて複合一意インデックスを作成するには、次のデータが一意になります。
フィールド1 | フィールド2 | 組み合わせ |
---|---|---|
1 | 1 | (1,1) |
1 | 2 | (1,2) |
2 | 1 | (2,1) |
2 | 2 | (2,2) |
次のデータには重複した値があります。
フィールド1 | フィールド2 | 組み合わせ |
---|---|---|
1 | 1 | (1,1) |
1 | 1 | (1,1) の繰り返し |
2 | 1 | (2,1) |
2 | 1 | (2,1) の繰り返し |
次に例を見ていきます。最初にコレクションの場所を作成します。
db.locations.insertOne({
address: "北京市丰台区莲花池东路118号北京西站",
latitude: 39.894793,
longitude: 116.321592
})
次に、緯度と経度に基づいて複合一意のインデックスを作成します。
db.locations.createIndex({
latitude: 1,
longitude: 1
},{
unique: true });
'latitude_1_longitude_1'
同じ経度の場所を挿入します。
db.locations.insertOne({
address: "北京市海淀区复兴路甲9号中华世纪坛",
lat: 39.910577,
long: 116.321592
})
複合インデックス latitude_1_longitude_1 が経度と緯度の結合値をチェックするため、操作は成功しました。
最後に、既存の緯度と経度を持つ場所を挿入します。
db.locations.insertOne({
address: "北京市丰台区莲花池东路118号北京西站",
latitude: 39.894793,
longitude: 116.321592
})
この時点で、MongoDB は重複キー エラーを返します。
MongoServerError: E11000 duplicate key error collection: book.locations index: latitude_1_longitude_1 dup key: {
lat: 39.894793, long: 116.321592 }