在 MongoDB 中不依赖唯一索引如何避免并发重复插入
使用 MongoDB 时,我们经常需要避免并发重复插入。通常情况下,我们会使用唯一索引,但有时我们可能无法使用唯一索引,或者唯一索引的性能开销太大。本文将介绍一种不依赖唯一索引的解决方案。
使用 setOnInsert
来避免重复插入。
func InsertOneIfNotExists(ctx context.Context, coll *mongo.Collection, filter bson.M, setOnInsert bson.M) error {
opts := options.Update().SetUpsert(true)
update := bson.M{"$setOnInsert": setOnInsert}
res, err := coll.UpdateOne(ctx, filter, update, opts)
if err != nil {
return err
}
if res.MatchedCount == 0 {
return nil
} else {
// 如果文档已存在,返回重复键错误
return mongo.WriteError{
Code: 11000, // MongoDB 重复键错误码
}
}
}
UpdateOne 方法的 upsert 参数为 true 时,如果文档不存在,则插入文档,如果文档存在,则更新文档。
UpdateOne 也是原子操作,不会被其他操作中断。
$setOnInsert
用于设置插入操作的值,如果文档不存在,则插入文档,如果文档存在,则不插入。
$setOnInsert
的值不会覆盖已存在的值,只会插入不存在的值。
返回的 res
中,MatchedCount
表示匹配到的文档数量,UpsertedID
表示插入的文档 ID。
如果 MatchedCount
为 0,则表示文档不存在,则插入文档,如果 MatchedCount
为 1,则表示文档存在,则更新文档。