0

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.

Sylvain Leroux
  • 50,096
  • 7
  • 103
  • 125
PaolaJ.
  • 10,872
  • 22
  • 73
  • 111
  • 1
    it helps to start writing some code. – Salvador Dali May 25 '15 at 09:12
  • @SalvadorDali 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 – PaolaJ. May 25 '15 at 09:16
  • @PaolaJ. I didn't see you last comment when I posted my answer. _"I tried ensure index by two fields (name, lastName) but it also didn't help"_ Could you show _how_ you created your index and _how_ you were able to insert two documents with the same `(name, lastName)̀` ? – Sylvain Leroux May 25 '15 at 10:53

1 Answers1

4

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.


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{"name", "lastName"},
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't know which one 
    }
    // Is another error
}
Community
  • 1
  • 1
Sylvain Leroux
  • 50,096
  • 7
  • 103
  • 125
  • @Sylvain Leroux Should I call this only once, in main or in init function, correct ? – PaolaJ. May 25 '15 at 09:46
  • @PaolaJ. I've edited the answer to provide additional informations and pointers to some related documentation. But as I am *not* a Go specialist, other answers might come with more details than I can provide. – Sylvain Leroux May 25 '15 at 10:36