findAndModify
in mongodb は素晴らしいのですが、どの埋め込みドキュメントを変更したかを知るのに少し苦労しています。
Post
これは、 embeds_manyの例ですComments
。(私は Mongoid ORM を使用していますが、質問はどの MongoDB セットアップにも共通です)。
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ですが、これを同時に実行している複数のプロセスがある場合select
、別のプロセスが予約したコメントを選択できます(競合状態)。
これは私が今持っている最も近いものです(プロセス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
これはうまくいくようです。これはこれを行うための最良の方法ですか、それともより良いパターンがありますか?