Mongoose 唯一索引不起作用!
我试图让 MongoDB 根据其索引检测重复值。我认为这在MongoDB中是可能的,但是通过猫鼬包装纸似乎被打破了。因此,对于这样的事情:
User = new Schema ({
email: {type: String, index: {unique: true, dropDups: true}}
})
我可以通过相同的电子邮件将2个用户保存。该死。
这里也在这里表达了同一问题: https://github.com/learnnboost/learnboost/mongoose/mongoose/56/56 ,但是那个线程是旧的,无处可去。
目前,我正在手动致电数据库以找到用户。该呼叫并不昂贵,因为“电子邮件”被索引。但是,让它在本地进行处理仍然很高兴。
有人有解决办法吗?
I'm trying to let MongoDB detect a duplicate value based on its index. I think this is possible in MongoDB, but through the Mongoose wrapper things appear to be broken. So for something like this:
User = new Schema ({
email: {type: String, index: {unique: true, dropDups: true}}
})
I can save 2 users with the same email. Darn.
The same issue has been expressed here: https://github.com/LearnBoost/mongoose/issues/56, but that thread is old and lead to nowhere.
For now, I'm manually making a call to the db to find the user. That call is not expensive since "email" is indexed. But it would still be nice to let it be handled natively.
Does anyone have a solution to this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
哎呀!你只需要重新启动 mongo 即可。
Oops! You just have to restart mongo.
并重新索引,用:
在测试中,由于我没有重要数据,您也可以这样做:
And re-index too, with:
In testing, since I don't have important data, you can also do:
我遇到了同样的问题:在将用户添加到数据库后,我将
email
字段的唯一约束添加到我们的UserSchema
中,并且仍然能够使用以下命令保存用户欺骗电子邮件。我通过执行以下操作解决了此问题:1)从用户集合中删除所有文档。
2) 从 mongo shell 中执行命令:
db.users.createIndex({email: 1}, {unique: true})
关于步骤 1,请注意 Mongo 文档中的内容:
https://docs.mongodb.com/manual/core/index-unique/
I ran into the same issue: I added the unique constraint for the
email
field to ourUserSchema
after already having added users to the db, and was still able to save users with dupe emails. I resolved this by doing the following:1) Remove all documents from the users collection.
2) From the mongo shell, execute the command:
db.users.createIndex({email: 1}, {unique: true})
Regarding step 1, note that from Mongo's docs:
https://docs.mongodb.com/manual/core/index-unique/
我做了这样的事情:
我添加了
Foo.createIndexes()
行,当代码运行时,我收到以下弃用警告:我不确定
Foo. createIndexes()
是异步的,但据我所知,事情似乎工作正常I've done something like this:
I added the
Foo.createIndexes()
line b.c. I was getting the following deprecation warning when the code was being ran:I'm not sure if
Foo.createIndexes()
is asynchronous, but AFAIK things seem to be working fine解决问题的步骤:
1 .将
unique: true
添加到属性中。2.删除集合 - 例如
role
(最后一行)name
)有重复的值3。重新启动使用
mongoose
库的 Node.js 服务器。这里的其他一些答案怎么不正确?
autoIndex
选项设置为true
重新启动数据库
按顺序执行上述 3 个步骤
Steps to fix the issue:
1 . Add
unique: true
to the attributes.2 . Drop the collection - for example
role
(last line)name
above)3 . Restart the Node.js server, that uses
mongoose
library.How some of other answers here, are not correct?
The
autoIndex
option is set totrue
Restart the db
in sequence
如果您在 Mongo 中留下了一些重复项,也会发生这种情况。当您的应用程序启动时,Mongoose 将尝试在 Mongo 中创建它们。
为了防止这种情况,您可以通过以下方式处理此错误:
This behavior happen also if you have left some duplicates in Mongo. Mongoose will try to create them in Mongo when your application starts up.
To prevent this, you can handle this error this way :
好的,我能够通过在字段上添加索引并设置唯一属性来从 mongoshell 解决此问题:
Shell 应该以这种方式响应:
现在从 mongoshell 快速测试:
应该给出:
WriteResult({ "nInserted" : 1 })
但是再次重复时:
将给出:
Ok, i was able to resolve this from the mongoshell by adding the index on the field and setting the unique property:
Shell should respond in this way:
Now to test quickly from the mongoshell:
Should give:
WriteResult({ "nInserted" : 1 })
But when repeating again:
Will give:
当出现以下情况时,Mongoose 将无法添加唯一索引:
在第一种情况下,使用
db.collection.getIndexes()
,并删除旧索引与db.collection.dropIndex("index_name")
。当您重新启动 Mongoose 应用程序时,它应该正确添加新索引。
在第二种情况下,您需要在重新启动 Mongoose 应用程序之前删除重复项。
Mongoose will silently fail to add a unique index when either:
In the first case, list the indexes with
db.collection.getIndexes()
, and drop the old index withdb.collection.dropIndex("index_name")
. When you restart the Mongoose application it should correctly add the new index.In the second case you need to remove the duplicates before restarting the Mongoose application.
根据文档:https://docs.mongodb.com/v2。 6/教程/修改索引/
不要重新启动 MONGO!
1 - 删除集合
2 - 重新索引表
According the documentation : https://docs.mongodb.com/v2.6/tutorial/modify-an-index/
DO NOT RESTART MONGO !
1 - drop the collection
2 - reindex the table
Mongoose 在从应用程序级别强制执行唯一索引时有点宽松;因此,最好使用 mongo cli 从数据库本身强制执行唯一索引,或者通过在 UserSchema 之后编写以下代码行来明确告诉 mongoose 您对唯一索引很重视:
UserSchema.index({ username: 1, email: 1 }, { unique: true});
这将在
username
和email< 上强制执行唯一索引UserSchema 中的 /code> 字段。干杯。
Mongoose is a little loose when enforcing unique indices from the application level; therefore, it's preferred to either enforce your unique indices from the database itself using the mongo cli or explicitly tell mongoose that you're serious about the
unique
index by writing the following line of code just after your UserSchema:UserSchema.index({ username: 1, email: 1 }, { unique: true});
This will enforce the unique index on both
username
andemail
fields in your UserSchema. Cheers.这是一个老问题,但对于仍然遇到此问题的任何人,您可能没有正确应用索引:
如果您将连接选项中的
autoIndex
设置为false
那么一个选择是使其成为true
或完全删除此属性,这会将其恢复为默认值true
,但是,在生产中不建议这样做,因为它会导致性能下降,更好的方法是在模型上显式调用createIndexes
,这将正确创建架构中定义的索引。因此原始问题中示例的语法如下:
an old question, but for anyone still having this issue, you probably are not applying indexes properly:
if you have
autoIndex
in connection options set tofalse
then one option would be to make it atrue
or remove this property altogether which would revert it to its default which istrue
, HOWEVER, this is not recommended in production as it would cause a hit to performance, the better approach would be to explicitly callcreateIndexes
on your model, which would properly create the indices as defined in your schema.so the syntax for the example in the original question can be as follows:
mongoose-unique-validator
如何使用此插件:
1) npm install - -save mongoose-unique-validator
2) 在您的模式中遵循以下指南:
3) mongoose 方法
当使用像
findOneAndUpdate
这样的方法时,您将需要传递此配置对象:{ runValidators: true, context : 'query' }
4) 附加选项
不区分大小写
在架构中使用 uniqueCaseInsensitive 选项
<代码>即。 email: { type: String, index: true, unique: true, required: true, uniqueCaseInsensitive: true }
自定义错误消息
<代码>即。 exampleSchema.plugin(uniqueValidator, { message: '错误,期望 {PATH} 是唯一的。' });
现在您可以向模式添加/删除唯一属性,而无需担心重新启动 mongo、删除数据库,或创建索引。
注意事项(来自文档):
因为我们依靠异步操作来验证数据库中是否存在文档,所以两个查询有可能同时执行一次,两者都返回 0,然后都插入到 MongoDB 中。
除了自动锁定集合或强制单个连接之外,没有真正的解决方案。
对于我们的大多数用户来说,这不会是一个问题,但这是一个需要注意的边缘情况。
mongoose-unique-validator
How to use this plugin:
1) npm install --save mongoose-unique-validator
2) in your schema follow this guide:
3) mongoose methods
When using methods like
findOneAndUpdate
you will need to pass this configuration object:{ runValidators: true, context: 'query' }
4) additional options
case insensitive
use the uniqueCaseInsensitive option in your schema
ie. email: { type: String, index: true, unique: true, required: true, uniqueCaseInsensitive: true }
custom error messages
ie. exampleSchema.plugin(uniqueValidator, { message: 'Error, expected {PATH} to be unique.' });
Now you can add/delete the unique property to your schemas without worrying about restarting mongo, dropping databases, or creating indexes.
Caveats (from the docs):
Because we rely on async operations to verify whether a document exists in the database, it's possible for two queries to execute at the same time, both get 0 back, and then both insert into MongoDB.
Outside of automatically locking the collection or forcing a single connection, there's no real solution.
For most of our users this won't be a problem, but is an edge case to be aware of.
最新答案:根本不需要重启mongodb,
如果 colleciton 已经具有同名索引,mongoose 将不会重新创建
再次你的索引,所以,首先删除 colleciton 的现有索引,
现在,当您运行 mongoose 时,它将创建新索引,
上述过程解决了我的问题。
Newest answer: there is no need to restart mongodb at all,
if colleciton has same name indexes already, mongoose will not recreate
your indexes again, so, drop colleciton's existing indexes firstly,
and now, when you run mongoose, it will create new index,
above process solved my problem.
重新启动和使用插件对我来说不起作用,而且使用插件来完成我们确信 mongo 可以自己完成的事情有点矫枉过正。
所以这是修复方法。在您的连接函数中将其添加到选项对象(第二个参数)
Restarting and using plugins didn't work for me plus it a little overkill to use plugins for something we're all sure mongo could do on it's own.
So here's the fix. in your connect function add this to the options object(2nd param)
我有一段时间遇到了同样的问题,并做了很多搜索,我的解决方案是 createIndexes() 函数。
我希望这有帮助。
所以代码会是这样的。
I faced the same issue for awhile and did a lot of searching and the solution for me was the
createIndexes()
function.I wish that helps.
so the code will be like that.
我通过在 mongodDB compass 中手动添加索引解决了这个问题。
我所做的步骤 - 我的计算机上安装了 MongoDB 指南针
users
集合。users
集合上,您将看到选项卡菜单并选择indexes
indexes
上,单击按钮Create Index
>。弹出窗口将显示电子邮件
选择
类型上,单击1(asc)
选项
上,选择checkbox创建唯一索引
就是这样。独特的功能应该有效。不要忘记将其添加到您的架构中。
例如
I fixed this issue by manually adding indexes in mongodDB compass.
Steps I did - I have MongoDB compass installed on my computer
users
collection.users
collection, You will see the tab menu and selectindexes
indexes
, click the buttonCreate Index
. The popup will show upemail
select
type, click1(asc)
options
, select the checkboxCreate unique index
And that is it. The unique functionality should work. Don't forget to add it in your schema.
e.g
您还可以通过删除索引来解决此问题;
假设您要从集合
users
和字段username
中删除唯一索引,请输入:db.users.dropIndex('username_1');
You can also resolve this issue by dropping the index;
let's assume you want to remove the unique index from collection
users
and fieldusername
, type this:db.users.dropIndex('username_1');
如果表/集合为空,则为该字段创建唯一索引:
如果表/集合不为空,则删除集合并创建索引:
现在重新启动 mongoDB。
If the table/collection is empty, then create unique index for the field:
If the table/collection is not empty, then drop the collection and create index:
Now restart mongoDB.
检查模式中的 autoIndex 是否为 true,当您使用 mongoose.connect 选项时,它可能设置为 false(默认 true)
check that autoIndex in the schema is true, it maybe set false(default true) when you use mongoose.connect options
什么对我有用 - 删除
对我不起作用的收集 - 重新启动服务器,重新启动 mongo
What worked for me- dropping collection
what did not work for me - restart server, restart mongo
这些答案都不适合我(必须手动创建索引),这是因为索引是在后台创建的,并且一旦建立连接我就播种数据。这意味着数据是在创建索引之前添加的,显然即使没有重复,一旦发生这种情况也不会创建索引(根据文档,这不应该是这样,但它这似乎已经发生了)。我知道有两种方法可以解决这个问题,而无需手动创建索引:
第一个也是最好的恕我直言,是在创建连接后使用 mongoose.connection.syncIndexes() 来重建索引匹配所有模式的所有集合(它甚至会在此过程中为您创建集合),并且只有当完成(.then() 或等待)时,您才播种数据或处理请求。
另一种方法是使用mongoose.model.createIndexes()为您想要确保索引的特定模型创建索引;您还必须在播种/处理之前执行此操作。
显然还有一个 EnsureIndexes() 方法
None of these answers worked for me (had to create my indexes manually), and it was because the indexes were being created in the background and I was seeding data as soon as a connection was established. This meant the data was added before the indexes were created, and apparently even though there was no duplicate, the indexes would not be created once this happens (according to the docs this shouldn't be so but it is what appears to have happened). There are two ways I know of to solve this without manually creating indexes:
The first- and best imho- is to use mongoose.connection.syncIndexes() after creating a connection to reconstruct the indexes of all collections to match all schemas (it will even create collections for you in the process), and only when this is complete (.then() or await) do you seed data or process requests.
An alternative is to use mongoose.model.createIndexes() to create indexes for the specific models you want to ensure indexes for; you also have to do this before seeding/processing.
Apparently there was also an ensureIndexes() method for this
只需删除集合。
很可能您在创建一些记录后将架构更新为“唯一”。因此,“独特”并没有按预期发挥作用。我获取了类似的问题并通过删除集合来解决它。
Just Drop the collection.
Most likely you updated the schema for "unique" after creating some records. So, "unique" is not working as expected. I fetched a similar issue and resolved it by dropping the collection.
如果您在连接方法中使用选项
autoIndex: false
,如下所示:mongoose.connect(CONNECTION_STRING, { autoIndex: false });
尝试删除该选项。如果这不起作用,请按照本线程中的建议尝试重新启动 mongodb。
If you are using the option
autoIndex: false
in the connection method like this:mongoose.connect(CONNECTION_STRING, { autoIndex: false });
Try removing that. If that doesn't work, try restarting mongodb as many suggested in this thread.
您可以将您的架构定义为
但是,当已经存在文档并且之后您更改了用户的架构时,这可能不起作用。如果您不想删除该用户集合,您可以为此用户集合创建电子邮件索引。使用此命令您可以创建电子邮件索引。
或者您可以删除集合并再次添加用户。
对于删除集合,您可以输入:
You can define your schema as
But maybe this will not work when there is already a document and after that, you have changed the schema of the User. You can create an index on email for this User collection if you don't want to drop the collection. Using this command you can create an index on email.
Or you can just drop the collection and add the user again.
For Dropping the collection, you can enter this:
当我遇到这个问题时,我多次尝试删除数据库、重新启动服务器(nodemon),但没有一个技巧完全不起作用。我通过 Robo 3T 找到了以下解决方法:
_id_
。现在,选择添加索引email
,例如Provide Keys as JSON。例如
<前><代码>{
“电子邮件”:1
}
单击唯一复选框
这将确保 MongoDB 中不会保存重复的电子邮件。
When I encountered this problem, I tried dropping the database, re-starting the server (nodemon) many times and none of the tricks didn't work at all. I found the following work around, through Robo 3T:
_id_
as the default. Now, choose Add Indexemail
for e-mail field, for exampleProvide Keys as JSON. For example
Click on the Unique checkbox
This will make sure no duplicate emails are saved in the MongoDB.
确保您的集合没有您刚刚放置唯一索引的字段的冗余。
然后重新启动您的应用程序(猫鼬)。
它只是默默地添加索引失败。
Make sure your collection has no redundant of the field you just put the unique index on.
Then just restart your app (mongoose).
It just silently add index fails.
从集合中删除所有文档:
正如其他人提到的那样,重新启动对我有用
Removing all documents from the collection:
And a restart, as others mentioned, worked for me
如果您的 MongoDB 作为服务运行(找到此问题的简单方法是,如果您不需要在不通过终端启动 mongod.exe 文件的情况下连接到数据库),那么在完成更改后,您可能需要重新启动服务和/或完全删除您的数据库。
这很奇怪,因为对于某些用户来说,只需删除一个集合就可以了。其中一些只需要删除数据库即可。但那些对我不起作用。我删除了数据库,然后重新启动了 MongoDB Server 服务。
要重新启动服务,请在 Windows 搜索栏上搜索“服务”,然后找到 MongoDB 服务,双击打开然后停止并再次启动该服务。
如果其他方法不适合您,我相信这可以完成这项工作。
If your MongoDB is working as a service (easy way of finding this is if you do not need to connect to the database without starting the mongod.exe file via terminal), then after doing the changes you might need to restart the service and/or drop your database fully.
It is quite strange because for some users just dropping a single collection worked. Some of them just needed to drop the database. But those did not worked for me. I dropped the database, then restarted the MongoDB Server service.
To restart a service search Services on the Windows search bar then find the MongoDB service, double click to open then stop and start the service again.
If the other methods did not work for you, I believe this will do the job.
就我而言,猫鼬已经过时了。我通过在 CMD 上运行 npm outdated 来检查它。
并更新了“猫鼬”。
请告诉您这是否也对您有用。
In my case mongoose was outdated. i checked it by running npm outdated on CMD.
and updated 'mongoose'.
Please tell if that worked for you as well.
当您将数据库与应用程序连接时,添加此选项:“audoIndex:true”
例如,在我的代码中,我这样做了:
我还删除了有问题的集合并重新创建它以确保它能够工作。
我在以下位置找到了此解决方案: https://dev.to/ emmysteven/已解决-mongoose-unique-index-not-working-45d5
我还尝试了“重新启动 MongoDB”等解决方案,但对我不起作用。
When you connect your database with the application add this option: "audoIndex: true"
for example in my code I did this:
I also dropped the collection that I have problem with and recreated it to make sure that it will work.
I found this solution at: https://dev.to/emmysteven/solved-mongoose-unique-index-not-working-45d5
I also tried solutions like "restart MongoDB" but didn't work for me.