10

GoでMongoDB用のmgoドライバーを使用しています。

私のアプリケーションはタスクを要求し(Mongoで「jobs」と呼ばれるコレクションからレコードを選択するだけで)、そのタスクを完了するために自分自身を担当者として登録します(同じ「job」レコードへの更新、自分自身を担当者として設定します)。

プログラムは複数のマシンで実行され、すべて同じMongoと通信します。私のプログラムが利用可能なタスクをリストしてから1つを選択すると、他のインスタンスがすでにその割り当てを取得している可能性があり、現在の割り当ては失敗します。

読んでから更新したレコードが、更新時に特定の値(この場合は担当者)を持っているかどうかを確認するにはどうすればよいですか?

どちらの割り当てでも取得しようとしているので、最初に保留中のタスクを選択して割り当てを試み、更新が成功した場合に備えて割り当てを保持する必要があると思います。

したがって、私のクエリは次のようになります。

「コレクション'jobs'のすべてのレコードから、assignee = null のレコードだけを更新し、IDを担当者として設定します。次に、そのレコードを渡して、ジョブを実行できるようにします。」

Go用のmgoドライバーでそれをどのように表現できますか?

4

3 に答える 3

42

これは古い質問ですが、誰かがまだ家で見ている場合に備えて、これはQuery.Applyメソッドを介して適切にサポートされています。別の回答に示されているようにコマンドを実行しますが、findAndModifyGogoodnessの背後に隠れているので便利です。

ドキュメントの例は、ここでの質問とほぼ正確に一致します。

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)
于 2013-08-20T23:24:55.860 に答える
2

MongoDBの担当者は、公式ドキュメントで同様のシナリオについて説明しています。http ://www.mongodb.org/display/DOCS/Atomic+Operations

基本的に、あなたがしなければならないのは、でどんな仕事でもフェッチすることassignee=nullです。あなたが後ろで仕事をしているとしましょう_id=42。次に、セレクターと更新されたドキュメントを使用してCollection.Update()assignee="worker1.example.com"を設定および呼び出すことにより、ドキュメントをローカルで変更できます。データベースがこのセレクターに一致するドキュメントをまだ見つけることができる場合、データベースはドキュメントをアトミックに置き換えます。それ以外の場合は、別のスレッドがすでにタスクを要求していることを示すErrNotFoundが表示されます。その場合は、再試行してください。{_id=42, assignee=null}

于 2012-07-10T17:41:47.350 に答える
2

選択した回答に対するコメントをご覧いただければ幸いですが、そのアプローチは正しくありません。選択してから更新すると、ラウンドトリップと2台のマシンが生成され、そのうちの1台がを更新する前に同じジョブをフェッチしますassigneefindAndModify代わりに次のメソッドを使用する必要があります: http ://www.mongodb.org/display/DOCS/findAndModify+Command

于 2012-09-10T15:35:27.833 に答える