MongoDB 中的唯一索引
在本文中,您将了解唯一索引,包括它们是什么以及如何在 MongoDB 中创建它们。 此外,简要描述了使用户的电子邮件在 MongoDB 中唯一的过程。
本文目录如下:
- MongoDB 中的唯一索引
- 在 MongoDB 中创建唯一索引
- MongoDB 中唯一索引的行为
- 使用 Mongoose 验证唯一电子邮件
MongoDB 中的唯一索引
唯一索引保证被索引的字段不包含重复值,确保被索引的字段是唯一的。 在构造集合期间,MongoDB 默认在 _id 列上生成唯一索引。
使用 db.collection.createIndex()
命令生成唯一索引,并将唯一选项设置为 true。
db.collection.createIndex( <key and index type specification>, { unique: true } )
单个字段的唯一索引
在 mongosh 中使用以下过程在成员集合的 user_id 字段上构建唯一索引。
db.members.createIndex( { "user_id": 1 }, { unique: true } )
唯一复合索引
在复合索引上,您还可以施加唯一限制。 例如,如果您对复合索引使用唯一约束,MongoDB 会在组合索引键值时强制执行唯一性。
在 mongosh 中使用以下操作在 members 集合的 groupNumber、lastname 和 firstname 字段上构建唯一索引。
db.members.createIndex( { groupNumber: 2, lastname: 1, firstname: 1 }, { unique: true } )
该索引确保 groupNumber、lastname 和 firstname 值的每个组合都是唯一的。
考虑以下带有以下文档的集合。
{ _id: 1, a: [ { loc: "A", qty: 5 }, { qty: 10 } ] }
在 a.loc
和 a.qty
上创建唯一的复合多键索引。
db.collection.createIndex( { "a.loc": 1, "a.qty": 1 }, { unique: true } )
以下文档可以包含在集合中,因为索引保证了 a.loc
和 a.qty
值组合的唯一性。
db.collection.insertMany( [
{ _id: 2, a: [ { loc: "A" }, { qty: 6 } ] },
{ _id: 3, a: [ { loc: "A", qty: 12 } ] }
] )
MongoDB 中唯一索引的行为
限制:
如果集合已经包含违反索引唯一要求的数据,MongoDB 将无法在提供的索引字段上建立唯一索引。 在散列索引上,您不能定义唯一约束。
使用副本集和分片集群创建唯一索引
使用滚动操作在副本集和分片集群上构建唯一索引需要在整个过程中停止对集合的所有写入。
如果您无法在此过程中停止对集合的所有写入,请不要使用滚动操作。 相反,通过发出以下命令为集合创建一个独一无二的索引:
-
副本集的主数据库上的
db.collection.createIndex()
-
分片集群的 mongos 上的
db.collection.createIndex()
跨单独文档的唯一约束
独一无二的要求适用于集合中的每个文档。 唯一索引防止索引键在不同文档中具有相同的值。
由于该限制仅适用于单独的文档,因此只要文档的索引键值与另一个文档的索引键值不重复,文档就可以具有导致唯一多键索引重复索引键值的项目数组。 在这种情况下,重复的索引条目只会进入索引一次。
例如,包含以下文档的集合。
{ _id: 1, a: [ { loc: "A", qty: 6 }, { qty: 10 } ] }
{ _id: 2, a: [ { loc: "A" }, { qty: 7 } ] }
{ _id: 3, a: [ { loc: "A", qty: 12 } ] }
在 a.loc 和 a.qty 上创建唯一的复合多键索引。
db.collection.createIndex( { "a.loc": 1, "a.qty": 1 }, { unique: true } )
如果该集合中没有其他文档具有 {"a.loc": "B", "a.qty": null}
的索引键值,则唯一索引允许将以下文档插入到集合中。
db.collection.insertOne( { _id: 4, a: [ { loc: "B" }, { loc: "B" } ] } )
唯一索引和缺失字段
如果唯一索引中的文档不包含索引字段的值,则索引将为该文档存储一个空值。 由于唯一性约束,MongoDB 将只允许一个文档缺少索引列。
如果有多个文档没有索引字段的值或索引字段丢失,则索引创建将失败并出现重复键错误。
例如,一个集合在 x 上有一个唯一索引。
db.collection.createIndex( { "x": 13 }, { unique: true } )
如果集合中还没有包含缺少字段 x 的文档,则唯一索引可以插入没有字段 x 的文档。
db.collection.insertOne( { y: 2 } )
但是,如果集合中已经有没有字段 x 的文档,则唯一索引将无法插入没有字段 x 的文档。
db.collection.insertOne( { z: 2 } )
由于违反了对字段 x 值的唯一约束,该操作无法插入文档。
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 12000,
"errmsg" : "E12000 duplicate key error index: test.collection.$a.b_1 dup key: { : null }"
}
})
唯一的部分索引
只有集合中与特定过滤器表达式匹配的文档才会在部分索引中建立索引。 因此,如果您同时使用 partialFilterExpression 和唯一约束,则唯一约束仅适用于与过滤器表达式匹配的文档。
如果文档不满足过滤要求,带有唯一性约束的部分索引不会禁止插入不满足唯一性约束的文档。
分片集群和唯一索引
在散列索引上,您不能定义唯一约束。
只有以下索引在范围分片集合中可以是唯一的。
- 分片键的索引值。
- 以前缀作为分片键的复合索引。
-
默认的
_id
索引; 但是,如果_id
字段不是分片键或分片键前缀,则_id
索引仅强制执行每个分片的唯一性要求。
唯一索引约束意味着:
- 如果集合具有其他待分片集合的唯一索引,则不能分片集合。
- 您不能为其他字段上已经分片的集合创建唯一索引。
稀疏和非稀疏唯一索引
从 MongoDB 5.0 开始,单个集合可以具有具有相同键模式的唯一稀疏和非稀疏索引。
独特而稀疏的索引创建
本例中创建了具有相同键模式和不同稀疏选择的多个索引。
db.scores.createIndex( { score : 2 }, { name: "unique_index", unique: true } )
db.scores.createIndex( { score : 2 }, { name: "unique_sparse_index", unique: true, sparse: true } )
基本和稀疏索引创建
使用和不使用稀疏选项,您都可以使用相同的键模式构建简单的索引。
db.scores.createIndex( { score : 2 }, { name: "sparse_index", sparse: true } )
db.scores.createIndex( { score : 2 }, { name: "basic_index" } )
基本索引和唯一索引中的重复键模式
使用 MongoDB 5.0,您可能拥有具有相同键模式的基本索引和唯一索引。 由于键模式的重复,向已经索引的字段添加唯一索引是可能的。
例子:
使用键模式 { score: 2 } 创建一个基本索引并插入三个文档。
db.scores.createIndex( { score : 1 }, { name: "basic_index" } )
db.scores.insert( { score : 1 } )
db.scores.insert( { score : 2 } )
db.scores.insert( { score : 4 } )
使用相同的键模式 { score: 2 }
创建唯一索引。
db.scores.createIndex( { score : 2 }, { name: "unique_index", unique: true } )
由于唯一索引,尝试插入重复的乐谱文档失败。
db.scores.insert( { score : 4 } )
使用 Mongoose 验证唯一电子邮件
使用 Mongoose,您可以使用验证来防止数据库中出现重复项。 Validation 定义在 Schema 类型中,是一个中间件。
您还可以在模式中创建验证或使用 Mongooses 的内置验证。 为防止重复,我们建议使用 unique 属性,因为它告诉 Mongoose 每个文档对于给定路径都应具有唯一值。
它是在电子邮件上创建 MongoDB 唯一索引的简写。
如果您等待索引建立,您可以使用 Mongoose 的基于承诺的事件,Model.init()
,如下所示。
const User = mongoose.model('User', mongoose.Schema({
email: {
type: String,
required: true,
match: /.+\@.+\..+/,
unique: true
}
}));
await User.create([
{ email: 'gmail@google.com' },
{ email: 'bill@microsoft.com' },
{ email: 'test@gmail.com' }
]);
await User.init();
try {
await User.create({ email: 'gmail@google.com' });
} catch(error) {
error.message; // 'E12000 duplicate key error...'
}
在本文中,将详细讨论 MongoDB 中的唯一索引。 此外,最后,唯一电子邮件的验证是在 MongoDB 的 mongoose 中完成的。
相关文章
比较 MongoDB 中的字段
发布时间:2023/04/21 浏览次数:51 分类:MongoDB
-
在本文中,我们将了解如何比较 MongoDB 中的两个字段。 此外,我们将看到一个相关的示例和解释,以使主题更容易理解。
清除或删除 MongoDB 中的集合
发布时间:2023/04/21 浏览次数:147 分类:MongoDB
-
本篇文章将告诉大家如何删除 MongoDB 数据库中的集合以及删除 MongoDB 中的集合的不同方法。
向 MongoDB 集合中的每个文档添加新字段
发布时间:2023/04/21 浏览次数:107 分类:MongoDB
-
您将在这篇文章中了解 $set 和 $setOnInsert 操作。 此外,利用这两个运算符,快速描述了向 MongoDB 中的集合添加字段的挑战。
MongoDB 截断集合
发布时间:2023/04/21 浏览次数:178 分类:MongoDB
-
可以根据需要选择两个选项之一来截断下面的集合。 在今天的文章中,我们将学习如何在 MongoDB 中截断集合。
删除 MongoDB 中的重复项
发布时间:2023/04/21 浏览次数:151 分类:MongoDB
-
在本文中,我们将了解如何删除 MongoDB 中的重复条目,并且我们还将看到一个带有适当解释的示例,以使主题更容易理解。
使用 NodeJS 检查 MongoDB 中是否存在集合
发布时间:2023/04/21 浏览次数:194 分类:MongoDB
-
在本文中,我们将检查 MongoDB 数据库中是否存在一个集合,并且我们还将查看与主题相关的示例,以使主题更容易理解。 为此,我们将使用 Node.js。
在 MongoDB 中创建索引
发布时间:2023/04/21 浏览次数:104 分类:MongoDB
-
索引有助于有效解决查询。 如果没有索引,MongoDB 必须遍历集合中的每个文档才能找到与查询匹配的文档。因此,在今天的文章中,我们将学习如何在 MongoDB 中创建索引。
MongoDB 中的稀疏索引
发布时间:2023/04/21 浏览次数:142 分类:MongoDB
-
在本文中,我们将讨论 MongoDB 中的稀疏索引。 此外,我们将提供一个相关示例并进行解释,以使该主题更容易理解。