《MongoDB入门教程》第30篇 唯一索引
创始人
2025-06-01 17:18:19
0

本文将会介绍 MongoDB 唯一索引,它可以用于确保文档字段值的唯一性。

唯一索引

很多时候我们需要确保文档中某个字段值的唯一性,例如 email 或者 username。唯一索引(unique index)可以帮助我们实现这种业务规则。实际上,MongoDB 使用唯一索引确保主键 _id 的唯一性。

创建唯一索引的方法和普通索引相同,只需要额外指定 {unique: true} 选项:

db.collection.createIndex({ field: 1}, {unique: true});

索引示例

首先,创建一个新的集合 users,插入一些文档:

db.users.insertMany([{ name: "张三", dob: "1990-01-01", email: "zhangsan@test.com"},{ name: "李四", dob: "1992-06-30", email: "lisi@test.com"}
]);

然后,我们基于 email 字段创建一个唯一索引:

db.users.createIndex({email:1},{unique:true});

接下来我们尝试插入一个已经存在的文档:

db.users.insertOne({ name: "张叁", dob: "1995-03-12", email: "zhangsan@test.com"}
);

此时,MongoDB 将会返回以下错误:

MongoServerError: E11000 duplicate key error collection: book.users index: email_1 dup key: { email: 'zhangsan@test.com' }

下面我们演示一下集合已经存在重复数据时如何创建唯一索引。首先删除并重建集合 users:

db.users.drop()db.users.insertMany([{ name: "张三", dob: "1990-01-01", email: "zhangsan@test.com"},{ name: "张叁", dob: "1995-03-12", email: "zhangsan@test.com"},{ name: "李四", dob: "1992-06-30", email: "lisi@test.com"}
]);

然后,基于 email 字段创建一个唯一索引:

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 }

以上错误的原因在于 email 中存在重复的记录。

通常,我们会在插入数据之前创建唯一索引,可以从头开始确保数据的唯一性。如果基于已有数据创建唯一索引,可能会由于重复数据导致索引创建失败。为此,我们需要删除重复的数据之后再创建索引。

例如,我们可以首先删除重复的 user:

db.users.deleteOne({ name: "张叁", dob: "1995-03-12", email: "zhangsan@test.com"});{ acknowledged: true, deletedCount: 1 }

然后基于 email 字段创建唯一索引:

db.users.createIndex({email: 1},{unique:true})email_1

复合唯一索引

基于多个字段创建的唯一索引就是复合唯一索引(unique compound index)。复合唯一索引可以确保多个字段值的组合唯一。例如,基于字段 field1 和 field2 创建复合唯一索引,以下数据具有唯一性:

field1field2组合
11(1,1)
12(1,2)
21(2,1)
22(2,2)

以下数据存在重复值:

field1field2组合
11(1,1)
11(1,1) 重复
21(2,1)
21(2,1) 重复

接下来我们看一个示例,首先创建一个集合 locations。

db.locations.insertOne({address: "北京市丰台区莲花池东路118号北京西站",latitude: 39.894793,longitude: 116.321592
})

然后,基于 latitude 和 longitude 创建一个复合唯一索引:

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 }

相关内容

热门资讯

日常等车时看到的行业细节 干了五年户外广告投放,养成了一个职业病:但凡路过公交候车亭,总会多看两眼——不是看广告好不好看,而是...
黄金回收行业标准制定有哪些核心... 贵金属回购市场的需求背景 近年来随着黄金投资和消费市场的发展,黄金回收相关需求持续攀升。不同群体的诉...
全球黑色星期二!AI交易“崩盘... 【导读】AI交易为何“崩盘”? 中国基金报记者 泰勒 大家,你们今天还好吗?! AI交易在全球范围内...
原创 6... 年初抢金条的人还在站岗,如今金店柜台前冷冷清清 黄金又跌了。 6月23日,伦敦现货黄金价格日内急跌逾...
狂融294亿美元!SK海力士冲... 韩国股市再度迎来重磅消息。 周三,韩国存储芯片龙头SK海力士宣布,计划在7月10日登陆纳斯达克,通过...
比特币跌破6万!AI吸走资金、... 比特币正在为机构化转型付出代价。散户买盘萎缩、ETF资金持续外流、企业持仓者潜在抛售压力上升,加之A...
原创 默... 欧洲近期试图复刻1985年广场协议的剧本,德国总理默茨呼吁欧盟27国联合行动,要求中国签订类似协议以...
怎么选 泛娱乐赛道直播公司孵化... 泛娱乐直播创业的行业发展背景 近年来泛娱乐直播赛道持续保持增长态势,据公开数据资料显示,2024年国...
原创 腰... 最近黄金市场凉得彻底。各大品牌足金饰品克价跌破1300元关口,北京菜百6月21日报价已经掉到1260...
ST中装:公司主要银行账户已全... 证券之星消息,ST中装(002822)06月24日在投资者关系平台上答复投资者关心的问题。 投资者提...
2026年开窗机行业趋势与战略... 一、开篇引言:市场格局重塑下的选择逻辑 步入2026年,全球建筑智能化与绿色节能政策的叠加驱动,使开...
资金全面转向科技,传统消费企业... 近期 A 股出现明显风格切换,老牌消费资金持续流出,机构与传统上市公司纷纷加码半导体、算力赛道。 先...
合肥保利翡翠天奕具体交房时间是... 对于众多购房者而言,“合肥保利翡翠天奕具体交房时间是什么时候?能按时交房吗?”是心中最关切的问题。根...
港股风向标|恒指连续杀跌后企稳... 财联社6月24日讯(编辑 冯轶)今日港股短线企稳,三大指数集体收涨。截至收盘,恒生指数涨0.33%,...
瑞众人寿达州中支被罚17万,涉... 蓝鲸新闻6月24日讯,近日,国家金融监督管理总局达州监管分局发布行政处罚决定书,剑指瑞众人寿保险有限...
美国最担心的事还是来了,中国加... 最近这段时间,国际金融圈子里有一笔账,算得各家央行心里都不太踏实。 截至2026年春季,美国国债总规...
马斯克,不是万亿富豪了 资产历史性超过万亿美元不到两周,特斯拉、SpaceX掌门人埃隆·马斯克的身价近日快速下跌。 据中新经...
突发!金价跌破4000美元,近... 每经记者:杜宇 记者|杜宇 编辑|何小桃 杜恒峰 校对|金冥羽 金银价格大跳水。 6月24日晚,现货...
粗粮吃越多越好?很多糖友吃错升... 控糖圈一直流传多吃粗粮稳血糖,不少糖友直接三餐全吃粗粮、顿顿杂粮,不仅胃胀消化不良,餐后血糖反而不降...
持续大跌!刚刚,黄金跌破400... 潮新闻客户端 记者 吴恩慧 6月24日,贵金属再次大跌。 截至发稿时,现货黄金大跌近3%,跌破400...