前言
Mongoose 是一个基于 Node.js 的 MongoDB 驱动程序,它为开发者提供了模式建模工具,同时支持中间件和其他常见的 ORM 功能,方便快速地在 Node.js 端建立和操作 MongoDB 数据库。但是,在使用 Mongoose 保存数据的过程中,如果遇到需要使用“唯一性约束(Unique)”的情况,有时候会遇到保存失败的问题。
本文将围绕“唯一性约束(Unique)”在 Mongoose 中保存的问题,详细讲解其中的原因,并提出多种解决方案,以期对广大前端开发者具有一定的学习和指导意义。
问题描述
在 Mongoose 中,如果给 Model 添加唯一性约束,意义是保证该字段值在整个数据库中是唯一的,避免重复的数据。例如,我们为 User Model 的 email 字段添加唯一约束:
-- -------------------- ---- ------- ----- ---------- - --- -------- ------ - ----- ------- ------- ----- -- ----- ------- ---- ------- --- ----- --------- - ---------------------- ------------
那么在插入数据时,如果插入的数据中 email 字段已经在数据库中存在,则插入操作将会失败:
-- -------------------- ---- ------- ----- ----- - --- ----------- ------ ------------------- ----- ----- ---- -- --- ------------------- ----- ----- - -- ----- - -------------------- - ---- - -------------------- - ---
但是,在实际应用过程中,有人会发现无论如何插入都会失败,并提示“E11000 duplicate key error collection”:
-- -------------------- ---- ------- ----- ----- - --- ----------- ------ ------------------- ----- ----- ---- -- --- ----- ----- - --- ----------- ------ ------------------- ----- ------ ---- -- --- ------------------- ----- ----- - -- ----- - -------------------- ----- - ---- - -------------------- ------ - --- ------------------- ----- ----- - -- ----- - -------------------- ----- - ---- - -------------------- ------ - ---
这时候我们需要解决这个问题,让数据顺利的存入数据库。
问题原因
Mongoose 中常常出现“Unique”约束失败的情况,是因为 MongoDB 的多个连接在进行保存操作时出现了竞争的情况,从而导致两个请求同时想要插入一条 email 字段值相同的数据,但实际只能有一个请求操作成功,另一个则失败。此时 Mongoose 就会报出上述的错误,提示要求在 email 字段上添加“唯一性约束”。
具体的原理是,MongoDB 使用了一个叫做“Write Concern” 的机制。在默认情况下,MongoDB 只保证一个操作被提交到副本集的主节点,并成功地进行了写入操作。因此,在多个连接并发操作时就会出现竞争问题。
解决方案
为了解决这个问题,我们需要考虑多个方面。以下是几种可行的方案:
1. 实现唯一性约束的错误处理
Mongoose 不支持结果集中的唯一键约束错误。不过,可以利用 MongoDB 向开发人员发送有关唯一键冲突的信息。
-- -------------------- ---- ------- ------------------- ----- ----- - -- ---- -- -------- --- ------ - ----------------------- ------------- - ---- -- ----- - -------------------- ----- - ---- - -------------------- ------ - ---
在上述代码中,我们直接访问错误代码 err,如果 code 值为 11000,就表示唯一性约束冲突,可以通过查询错误消息 err.message 获取更具体的错误信息。
2. 使用批量更新
Mongoose 可以利用 MongoDB 提供的批量更新功能来规避唯一性约束的错误。通过使用 $setOnInsert 和 upsert 选项来设置一个对象。
-- -------------------- ---- ------- ------------------------ ------------- - ------------- - ------ ------------ ----- ----------- ---- ---------- - -- -------- ------ -------- ----- ------- - -- ----- - -------------------- ----- - ---- - -------------------- -------- - ---
在上述代码中,使用 mongoose 的model的 update 方法来更新数据库的记录,如果 email 字段已经存在,则更新相应的值,否则进行插入操作。
3. 降低竞争条件
可以降低竞争条件来解决“Unique”约束失败的情况。
-- -------------------- ---- ------- ------------------- ------ ----------- -- ------------- ---- - ------- - ------------------- ------- - ------- - ----------------------- ----- ------- - ------------------------ ----- - -- ----- - -------------------- ----- - ---- - -------------------- ------ - -- --
在上述代码中,我们先查询数据库中是否已存在 email 值相同的数据,如果存在,则返回或更新。如果不存在,则再进行插入操作。
总结
通过本文的介绍,我们了解到了“唯一性约束(Unique)”在 Mongoose 中保存失败的各种情况。对于任何一种技术问题,都需要我们认真分析其原因,并且采用合适的解决方案,从而解决问题。遇到“唯一性约束(Unique)”约束失败的问题时,我们需要注意减少连接并发操作产生的竞争冲突;可以利用批量更新、错误信息提示等方式解决问题。我们希望本篇文章对广大前端开发者具有一定的学习和指导意义。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/651eac0e95b1f8cacd658cbf