Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB in Go (golang) with mgo: How do I update a record, find out if update was successful and get the data in a single atomic operation?

Tags:

mongodb

go

mgo

I am using mgo driver for MongoDB under Go.

My application asks for a task (with just a record select in Mongo from a collection called "jobs") and then registers itself as an assignee to complete that task (an update to that same "job" record, setting itself as assignee).

The program will be running on several machines, all talking to the same Mongo. When my program lists the available tasks and then picks one, other instances might have already obtained that assignment, and the current assignment would have failed.

How can I get sure that the record I read and then update does or does not have a certain value (in this case, an assignee) at the time of being updated?

I am trying to get one assignment, no matter which one, so I think I should first select a pending task and try to assign it, keeping it just in the case the updating was successful.

So, my query should be something like:

"From all records on collection 'jobs', update just one that has assignee=null, setting my ID as the assignee. Then, give me that record so I could run the job."

How could I express that with mgo driver for Go?

like image 696
Sebastián Grignoli Avatar asked Jul 10 '12 16:07

Sebastián Grignoli


2 Answers

This is an old question, but just in case someone is still watching at home, this is nicely supported via the Query.Apply method. It does run the findAndModify command as indicated in another answer, but it's conveniently hidden behind Go goodness.

The example in the documentation matches pretty much exactly the question here:

change := mgo.Change{
        Update: bson.M{"$inc": bson.M{"n": 1}},
        ReturnNew: true,
}
info, err = col.Find(M{"_id": id}).Apply(change, &doc)
fmt.Println(doc.N)
like image 56
Gustavo Niemeyer Avatar answered Sep 24 '22 20:09

Gustavo Niemeyer


I hope you saw the comments on the answer you selected, but that approach is incorrect. Doing a select and then update will result in a round trip and two machines and be fetching for the same job before one of them can update the assignee. You need to use the findAndModify method instead: http://www.mongodb.org/display/DOCS/findAndModify+Command

like image 35
Steven Luu Avatar answered Sep 25 '22 20:09

Steven Luu