我试图让MongoDB根据其索引检测重复值。 我认为这在MongoDB中是可能的,但是通过Mongoose包装器,事情似乎被打破了。 所以对于这样的事情:
User = new Schema ({
email: {type: String, index: {unique: true, dropDups: true}}
})
我可以用同一封电子邮件保存2个用户。 真是
在这里也表达了相同的问题:https://github.com/LearnBoost/mongoose/issues/56,但是该线程很旧,导致无处可去。
现在,我正在手动调用数据库以查找用户。 由于对"电子邮件"进行了索引,因此该调用并不昂贵。 但是让它在本地处理仍然会很好。
有人对此有解决方案吗?
坏消息,仍然是mongod v2.4.3,mongoose v3.6.20的问题
唯一性似乎可以在我的一台主机上工作,但是无法在另一台主机上使用完全相同的节点/猫鼬代码来强制执行唯一性。 运行正常的主机运行单个mongod 3.4.10,而不运行单个mongod 3.4.10-运行具有mongod 3.2.17的副本集。在这两个主机上,Im从头开始创建一个集合,因此现有的复制不是问题。 我已经尝试过此页面上的大多数解决方案,而有效的解决方案是@Isaac Pak的mongoose-unique-validator。
糟糕!您只需要重新启动mongo。
我遇到同样的问题,但是我找不到如何在OSX上重新启动mongo的方法。当我终止该进程时,它将再次自动产生,并且唯一索引仍然不起作用...有什么想法吗?
您是什么意思"哎呀,您只需要重启mongo" ?!您是在说不关闭数据库就不可能添加索引吗?
这不是真的。您无需重新启动mongo即可添加索引。
为独特的事情..我不得不重启mongo ..并且它起作用..谢谢!
我尝试重新启动。也重新索引。不得不删除数据库来解决这个问题。猜测问题是添加索引之前已经存在重复项,因此在生产数据库中,我需要删除重复项然后重新启动?
我认为这是最短的答案。
@isimmons删除收藏集对我有用。感谢您的评论。
我重新启动了mongod并退出了所有客户端,然后重新启动了mongod,但仍然出现相同的行为。我正在使用mongo v3.4.17和mongoose 5.2.15。我收到有关collection.ensureIndex的弃用警告,但它告诉我改用createIndexes,所以我测试了Model.createIndexes()...
Oops! You just have to restart mongo.
并使用以下方法重新编制索引:
mongo
> db..reIndex()
在测试中,由于我没有重要数据,因此您也可以执行以下操作:
mongo
> db.dropDatabase()
db.dropDatabase()擦除数据库!
我遇到了同样的问题:在已经将用户添加到数据库之后,我将email字段的唯一约束添加到了我们的UserSchema中,并且仍然能够使用重复电子邮件保存用户。我通过执行以下操作解决了这个问题:
1)从用户集合中删除所有文档。
2)在mongo shell中,执行命令:
db.users.createIndex({email: 1}, {unique: true})
关于步骤1,请注意,来自Mongo的文档:
MongoDB cannot create a unique index on the specified index field(s) if the collection already contains data that would violate the unique constraint for the index.
https://docs.mongodb.com/manual/core/index-unique/
这对我来说很完美
这对我有用
如果您在Mongo中保留了一些重复项,也会发生此行为。当您的应用程序启动时,Mongoose将尝试在Mongo中创建它们。
为了防止这种情况,您可以通过以下方式处理此错误:
yourModel.on('index', function(err) {
if (err?) {
console.error err
}
);
好的,我可以通过在字段上添加索引并设置unique属性来从mongoshell中解决此问题:
db..ensureIndex({fieldName: 1}, {unique: true});
Shell应该以这种方式做出响应:
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
现在从mongoshell快速测试:
var doc = {fieldName: 'abc'};
db..insert(doc)
应该给:
WriteResult({" nInserted":1})
但是,当再次重复时:
db..insert(doc)
会给:
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" :"insertDocument :: caused by :: 11000 E11000 duplicate key error index: fuelConsumption.users.$email_1 dup key: { : "martyna@martycud.com" }"
}
})
这还告诉您已经存在哪些重复条目。
从应用程序级别强制执行唯一索引时,猫鼬有点松散;因此,最好是使用mongo cli从数据库本身强制您的唯一索引,或者通过在UserSchema之后编写以下代码行来明确告诉mongoose您对unique索引很认真:
UserSchema.index({ username: 1, email: 1 }, { unique: true});
这将在UserSchema的username和email字段上强制使用唯一索引。干杯。
晚了一点,但是ORM有什么好处,那就是"强制执行唯一索引时有点松动"
轻浮的评论毫无用处,这有什么用。该解决方案是可靠的并且已经可以生产。
我做了这样的事情:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const FooSchema = new Schema({
name: { type: String, required: true, index: true, unique: true }
});
const Foo = mongoose.model('Foo', FooSchema);
Foo.createIndexes();
module.exports = Foo
我添加了Foo.createIndexes()行b.c.运行代码时,我收到以下弃用警告:
(node:21553) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.
我不确定Foo.createIndexes()是否异步,但是AFAIK似乎工作正常
该问题的唯一答案是解决问题而不是围绕问题解决。
根据文档:https://docs.mongodb.com/v2.6/tutorial/modify-an-index/
To modify an existing index, you need to drop and recreate the index.
不要重启MONGO!
1-删除集合
db.users.drop()
2-重新索引表格
db.users.ensureIndex({email: 1, type: 1}, {unique: true})
猫鼬唯一验证器
如何使用此插件:
1)npm install-保存猫鼬唯一验证器
2)在您的架构中,请遵循以下指南:
// declare this at the top
var mongoose = require('mongoose');
var uniqueValidator = require('mongoose-unique-validator');
// exampleSchema = mongoose.Schema({}) etc...
exampleSchema.plugin(uniqueValidator);
// module.exports = mongoose.model(...) etc....
3)猫鼬的方法
使用findOneAndUpdate之类的方法时,您需要传递此配置对象:
{ runValidators: true, context: 'query' }
ie. User.findOneAndUpdate(
{ email: 'old-email@example.com' },
{ email: 'new-email@example.com' },
{ runValidators: true, context: 'query' },
function(err) {
// ...
}
4)其他选项
不区分大小写
在模式中使用uniqueCaseInsensitive选项
ie. email: { type: String, index: true, unique: true, required: true, uniqueCaseInsensitive: true }
自定义错误消息
ie. exampleSchema.plugin(uniqueValidator, { message: 'Error, expected {PATH} to be unique.' });
现在,您可以向架构中添加/删除唯一属性,而不必担心重启mongo,删除数据库或创建索引。
注意事项(来自文档):
因为我们依靠异步操作来验证数据库中是否存在文档,所以有可能同时执行两个查询,两个查询都返回0,然后都插入到MongoDB中。
除了自动锁定集合或强制单个连接之外,没有真正的解决方案。
对于我们大多数用户来说,这不是问题,但是这是一个边缘情况。
您也可以通过删除索引来解决此问题。
假设您要从集合users和字段username中删除唯一索引,请输入以下内容:
db.users.dropIndex('username_1');
最新答案:根本不需要重新启动mongodb,
如果colleciton已经具有相同的名称索引,猫鼬将不会重新创建
再次创建索引,因此,首先删除大学的现有索引,
现在,当您运行猫鼬时,它将创建新索引,
以上过程解决了我的问题。
检查模式中的autoIndex是否为true,使用mongoose.connect选项时可能将其设置为false(默认为true)
如果表/集合为空,则为该字段创建唯一索引:
db..createIndex({'field':1}, {unique: true})
如果表/集合不为空,则删除集合并创建索引:
db..drop()
db..createIndex({'field':1}, {unique: true})
现在重新启动mongoDB。
遇到此问题时,我尝试删除数据库,并多次重新启动服务器(nodemon),但所有技巧都没有用。通过Robo 3T,我发现以下解决方法:
在Robo 3T中,双击数据库以打开集合
打开收藏集以显示有问题的收藏集。首先,请确保您的收藏集为空
用鼠标右键单击索引文件夹。默认情况下,您将看到_id_作为默认值。现在,选择添加索引
选择一个名称,例如在电子邮件字段中说email
提供密钥作为JSON。例如
{
"email": 1
}
单击唯一复选框
救
这将确保在MongoDB中不会保存重复的电子邮件。
如果在这样的连接方法中使用选项autoIndex: false:
mongoose.connect(CONNECTION_STRING, { autoIndex: false });
尝试删除它。如果这样不起作用,请尝试按照此线程中的建议重新启动mongodb。
您可以将架构定义为
User = new Schema ({
email: {
type: String,
unique: true
}
})
但是,当已经有一个文档,然后又更改了用户的架构时,这可能无法正常工作。如果您不想删除该用户集合,则可以在电子邮件上为其创建索引。使用此命令可以在电子邮件上创建索引。
db.User.createIndex({email:1},{unique: true})
或者,您可以删除集合并再次添加用户。
对于删除集合,您可以输入以下内容:
db.User.drop()
我有一段时间遇到相同的问题,并进行了大量搜索,而对我来说,解决方案是createIndexes()函数。
希望对您有所帮助。
因此代码将是这样。
User = new Schema ({
email: {type: String, unique: true}
});
User.createIndexes();