How to prevent to multiple goroutines inserts document in persons collections if already exists person with same name and last name?

huangapple go评论93阅读模式
英文:

How to prevent to multiple goroutines inserts document in persons collections if already exists person with same name and last name?

问题

如何防止多个goroutine在persons集合中插入文档,如果已经存在具有相同姓名和姓氏的人?

type Person struct {
    Id       bson.ObjectId `bson:"_id"`
    Name     string        `bson:"name"`
    LastName string        `bson:"lastName"`
}

我正在使用Go语言的mgo驱动程序与Mongo一起使用。

我尝试在插入之前查找是否存在具有相同姓名和姓氏的文档,但我不认为这能覆盖两个goroutine同时检查的整个情况。我尝试通过两个字段(name,lastName)来确保索引,但这也没有帮助。

英文:

How to prevent multiple goroutines to insert document in persons collections if already exists person with same name and last name ?

type Person struct {

	Id        				bson.ObjectId 	`bson:"_id"`
	Name 			string        	`bson:"name"`
	LastName 			string        	`bson:"lastName"`

}

I am using Mongo with mgo driver for go language.

I try to find before insert if there is a document with same name and last name but I don't think that cover whole case when both goroutines check in same time. I tried ensure index by two fields (name, lastName) but it also didn't help.

答案1

得分: 4

如何防止多个_goroutines/process/thread/applications/..._在persons集合中插入重复的文档,如果已经存在相同姓名和姓氏的人?

唯一的方法是在{name:1, lastname:1}上使用唯一索引来防止重复的条目,然后在代码中,你应该准备好优雅地处理由潜在冲突引起的异常。

绝对不要在插入之前进行检查,因为在MongoDB中你没有事务,所以很可能在你的检查和插入之间,另一个客户端并发地插入了一条记录。

<hr>

其他人可能会更好地帮助你使用正确的Go语法,但以下代码片段(来自这里)可以帮助你创建所需的索引:

index := mgo.Index{
Key: []string{"name", "lastName"},
Unique: true,
}
 
err = c.EnsureIndex(index)

然后,每次插入文档时,你需要使用mgo.isDup函数来测试错误是否由重复键引起。以下是来自之前由@elithrar回答的示例

err := users.Insert(user) // 其中user是*mgo.Collection类型
if err != nil {
    if mgo.IsDup(err) {
        // 是重复键,但我们不知道是哪一个
    }
    // 是其他错误
}
英文:

> How to prevent to multiple goroutines/process/thread/applications/... to insert documents in persons collections if already exists person with same name and last name

The only way to prevent duplicate entries esp. in concurrent environment is by using an unique index on {name:1, lastname:1}. Then in your code, you should be prepared to gracefully handle the exception raised by a potential collision.

Never ever check-before-insert, as in MongoDB you don't have transaction, so it is quite possible that a record was concurrently inserted by an other client after your check and before your insert.

<hr>

Other peoples might certainly help you more with the correct Go syntax, but something along the lines of the following code (borrowed from here) will allow you to create the required index:

index := mgo.Index{
Key: []string{&quot;name&quot;, &quot;lastName&quot;},
Unique: true,
}
 
err = c.EnsureIndex(index)

Then, every time you insert a document, you need to use the mgo.isDup function to test if an error was caused by a duplicate key. As an example from a previous answer by @elithrar:

err := users.Insert(user) // where user is type *mgo.Collection
if err != nil {
    if mgo.IsDup(err) {
        // Is a duplicate key, but we don&#39;t know which one 
    }
    // Is another error
}

huangapple
  • 本文由 发表于 2015年5月25日 17:07:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/30434742.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定