1

findAndModify in mongodb is great, but I am having a little trouble knowing which embedded document I modified.

Here is an example where a Post embeds_many Comments. (I'm using Mongoid ORM but the question is generic to any MongoDB setup).

begin
  p = Post.asc(id).where(comments: { '$elemMatch' => {reserved: false} }).find_and_modify({'$set' => {'comments.$.reserved' => true}}, {new: true}
  # now i need to find which comment I just reserved
  c = p.comments.select{|c| c.reserved }.first
  ...
ensure
  c.update_attribute :reserved, false
end

Ok this sort of works, but if I have multiple processes running this simultaneously my select could choose a comment that another process had reserved (race condition).

This is the closest I have for now (reserving by process id):

begin
  p = Post.asc(id).where(comments: { '$elemMatch' => {reserved: nil} }).find_and_modify({'$set' => {'comments.$.reserved' => Process.pid}}, {new: true}
  # now i need to find which comment I just reserved
  c = p.comments.select{|c| c.reserved == Process.pid }.first
  ...
ensure
  c.update_attribute :reserved, nil
end

Which seems to work. Is this the best way to do this or is there a better pattern?

Brian Armstrong
  • 19,707
  • 17
  • 115
  • 144
  • 1
    I don't quite understand how they can be a race condition - findAndModify is atomic. Could you post a sample document - maybe it would be more clear then the case you are worried about. – Asya Kamsky Feb 05 '13 at 04:21
  • @BrianArmstrong Are y facing race conditions or it ur assumption because as Asya said findAndModify is and atomic operation – Viren Feb 13 '13 at 08:13

1 Answers1

0

Was able to solve it by generating a SecureRandom.hex and setting this on the embedded document with find_and_modify. Then you can loop through the embedded documents and see which one has your matching hex, to see which one you are working with.

Brian Armstrong
  • 19,707
  • 17
  • 115
  • 144