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 Shell 中列出所有数据库
发布时间:2023/05/11 浏览次数:180 分类:MongoDB
-
交互式 Mongo Shell 提供了多个用于获取数据的选项。 本文介绍了在 Mongo Shell 中列出数据库的几种不同方法。
MongoDB 中检查字段包含的字符串
发布时间:2023/05/11 浏览次数:1024 分类:MongoDB
-
这篇文章解决了如何在 MongoDB 中使用正则表达式来确定字段是否包含字符串。在 MongoDB 中使用正则表达式 正则表达式 (regex) 是定义搜索模式的文本字符串。
在 MongoDB 中 upsert 更新插入
发布时间:2023/05/11 浏览次数:214 分类:MongoDB
-
在 MongoDB 中,upsert 结合了更新和插入命令。 它可以在 update() 和 findAndModify() 操作中使用。MongoDB 中的 upsert 查询 upsert 采用单个布尔参数。
如何卸载 MongoDB
发布时间:2023/05/11 浏览次数:745 分类:MongoDB
-
要从您的计算机中卸载 MongoDB,您必须先删除 MongoDB 服务、数据库和日志文件。使用这篇 MongoDB 文章,您将能够从 Ubuntu Linux、Mac 和 Windows 卸载 MongoDB。 请务必保留数据备份,因为一旦卸载,便
在 MongoDB 中存储日期和时间
发布时间:2023/05/11 浏览次数:762 分类:MongoDB
-
本 MongoDB 教程解释了 Date() 对象是什么以及如何使用 Date() 方法对集合进行排序。 这也将帮助您找到在 MongoDB 中显示和存储日期/时间的最佳方法。
MongoDB 按 ID 查找
发布时间:2023/05/11 浏览次数:1856 分类:MongoDB
-
MongoDB 中的 find by Id() 函数用于获取与用户提供的 id 相匹配的文档。 如果找不到与指定 ID 匹配的文档,则返回空值。
检查 MongoDB 服务器是否正在运行
发布时间:2023/05/11 浏览次数:247 分类:MongoDB
-
这篇 MongoDB 教程将告诉您如何检查是否安装了 MongoDB 以及安装的 MongoDB 服务器的版本。 它在 Windows、UBUNTU 和 MAC 等不同的操作系统中实现。
MongoDB 中的分页
发布时间:2023/05/11 浏览次数:174 分类:MongoDB
-
这篇文章将介绍什么是 MongoDB 中的分页。 为什么在 MongoDB 中需要分页以及在 MongoDB 中完成分页的不同方法或方式是什么。
MongoDB 从查询开始
发布时间:2023/05/11 浏览次数:186 分类:MongoDB
-
在这篇 MongoDB 文章中,用户将学习如何使用 $regex 进行开始查询。 它为查询中的模式匹配字符串提供正则表达式功能。