我使用以下模型:
const { model, Schema } = require('mongoose');
const userSchema = new Schema({
name: String,
email: { type: String, unique: true },
password: String,
});
const User = model('User', userSchema);
module.exports = { userSchema, User };
和
const { model, Schema } = require('mongoose');
const { userSchema } = require('./user');
const shopSchema = new Schema({
name: String,
address: String,
contact: { type: String, unique: true },
createdBy: userSchema,
updatedBy: userSchema,
});
const Shop = model('Shop', shopSchema);
module.exports = { shopSchema, Shop };
现在的问题是:当我从数据库中找到一个 user
并将其分配给 createdBy
和 updatedBy
字段时,出现重复键错误。代码如下:
const { Shop } = require('./shop');
const { User } = require('./user');
const user = await User.findById(id);
const shop = new Shop({ createdBy: user, updatedBy: user });
下面是错误:
MongoError: E11000 duplicate key error collection: database.shops index: updatedBy.email dup key: { updatedBy.email: "foo@bar.baz" }
为什么会出现此错误,我该如何解决?
答案 0 :(得分:1)
问题是集合中已经有另一个文档,其中 createdAt.email
和 updatedAt.email
与我想要插入的文档相匹配。例如:
_id: ObjectId("...")
name: "..."
address: "..."
contact: "..."
createdBy: Object
_id: ObjectId("...")
email: "foo@bar.baz"
updatedBy: Object
_id: ObjectId("...")
email: "foo@bar.baz"
已经存在,我尝试添加另一个文档,这些字段的值相等。
但这在这里不应该是一个问题,因为我没有将该文档分配给它的父文档,而是在作为子文档的不同集合中。所以它不应该担心重复密钥问题。现在我需要知道有没有什么方法可以告诉MongoDB/Mongoose不要担心这个问题。
Mongoose 实际上支持嵌套子文档的索引排除。详情请见here。您所要做的就是将第二个参数传递给 Schema
构造函数,这是一个您指定不索引子路径的对象。像这样:
const shopSchema = new Schema(
{
//...
},
{
excludeIndexes: true,
}
);
答案 1 :(得分:0)
你这样定义电子邮件
email: { type: String, unique: true }
当一个字段为unique
时,mongoose对其进行索引,当一个字段为索引时,集合中应该只有一个数字,所以
第一种方法:在删除集合后,您应该从电子邮件中删除 unique: true
以完全删除索引或使用命令删除索引
第二种方式:将使用模型放在一个字段中,在createdBy
或updatedBy
中,
当您将 User 放在一个集合中的两个字段中时,因此创建了重复键