我遇到了通过nodejs将数据插入mongo的问题。我通过upsert:true
或在返回的mongoose文档上调用.save()
将json对象加载到文档中。
编辑:我忘了指出一点,这确实有效。我正确更新了30-40,000份文件。它将运行一段时间,然后最终抛出此错误。 “唯一键(xId
)每次都是一个不同的字符串,所以我认为它不是由实际加载的数据引起的......
这是架构:
var rosterSchema = new Schema({
name : String,
xId : {type:String, unique: true},
event : {type:ObjectId, ref:'Event'},
team : {type:ObjectId, ref:'Team'},
division : {type:ObjectId, ref:'Division'},
place : String,
players : [{type:ObjectId,ref:"Player"}],
staff : [{type:ObjectId,ref:"Player"}],
matches : [{type:ObjectId,ref:"Match"}],
});
错误:
MongoError: E11000 duplicate key error collection: r_fix.rosters index: xId_1 dup key: { : "6RNoYBSsCAJRsjxs" }
at Function.MongoError.create
解析/加载函数的每次运行都以单个名单页面为目标,该页面引用其匹配中的其他名单。
大多数名单已经存在加载其他数据。
我无法保证将解析名单的顺序,因此我可能需要针对尚不存在的名册创建“匹配”,这需要创建新名单,因此我使用findOneAndUpdate
而不是find
知道可能导致这种情况的原因是什么?我试图避免粘贴整个来源,所以这些是每个单独的电话,我认为是相关的信息:
var rosterObj = {
xId : id,
name : rosterJson.team_name,
};
Roster.findOneAndUpdate({xId:rosterObj.xId},{$set:rosterObj},{new: true, upsert: true, setDefaultsOnInsert: true})
.exec((err,roster)=>{
if(err)throw(err);
}).then((roster)=>{
...
上述名单将返回所有后续save()
的
roster.event = event._id;
roster.save((err)=>{if(err)throw(err)})
...
roster.team = team._id;
roster.save((err)=>{if(err)throw(err)})
...
if(pObj.staff == "No")
roster.players.addToSet(player._id);
else
roster.staff.addToSet(player._id);
roster.save((err)=>{if(err)throw(err)});
...
if(!roster.event)
if(oppRoster.event){
roster.event = oppRoster.event;
roster.save((err)=>{if(err)throw(err)});
}
...
var rosterObj = {
xId:mObj.vs.roster_id,
event:roster.event,
}
Roster.findOneAndUpdate({xId:rosterObj.xId},{$set:rosterObj},{new: true, upsert: true, setDefaultsOnInsert: true}).exec((err,oppRoster)=>{
if(err)throw(err);
return oppRoster;
})
据我了解,当我使用单个密钥进行查找时,它是文档中唯一的unique:true
值,那么doc.save()
和doc.findOneAndUpdate({ ... , {upsert :true...})
永远不会返回重复键错误。
我在承诺链末尾的catch()
也没有抓住这些抛出的错误,但这是一个完全不同的问题。
但我什么都不知道,所以我就在这里!
编辑:我应该指出,我在大量文档中这样做,但它们都是有希望链接的,所以只有一个'名册'应该一次更新。答案 0 :(得分:1)
唯一索引约束本身不会保护您免受重复键错误的影响,只能保护您重复记录。您需要捕获异常并重试。由于此时竞争条件危险已经过去,因此重复键错误不应再次发生。请参阅:https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/#behavior