あなたが言うように、あなたが望むことをするためのきれいな方法は現在ありません。現時点で必要な操作のような操作に最適なアプローチは次のとおりです:
- リーダーは適切な制限と並べ替えでXドキュメントを選択します
- Readerは、1)によって返されたドキュメントに、独自の一意のリーダーID(
e.g. update({_id:{$in:[<result set ids>]}, state:"available", $isolated:1}, {$set:{readerId:<your reader's ID>, state:"processing"}}, false, true)
) - リーダーは、処理としてマークされ、独自のリーダーIDを持つすべてのドキュメントを選択します。この時点で、結果のドキュメントセットに排他的にアクセスできることが保証されます。
- 3)の結果セットを処理用に提供します。
リーダーは別のリーダーによってまだ予約されていないドキュメントを予約できないため、これは非常に同時の状況でも機能することに注意してください(ステップ2は現在利用可能なドキュメントのみを予約でき、書き込みはアトミックです)。予約をタイムアウトできるようにしたい場合は、予約時刻を含むタイムスタンプも追加します(たとえば、リーダーがクラッシュ/失敗する可能性があるシナリオの場合)。
編集:詳細:
書き込みに比較的長い時間がかかる場合、すべての書き込み操作で保留中の操作が発生することがあります。これは、次の手順を実行しない限り、手順2)で手順1)でマークされたすべてのドキュメントが表示されない可能性があることを意味します。
- 適切な「w」(懸念事項を書く)値を使用します。これは1以上を意味します。これにより、書き込み操作が呼び出された接続は、結果に関係なく、完了するのを待つようになります。
- 手順2の読み取りを、同じ接続(slaveOkが有効な読み取りのレプリカセットにのみ関連)またはスレッドで実行して、シーケンシャルであることが保証されるようにしてください。前者は、ほとんどのドライバーで「requestStart」メソッドや「requestDone」メソッドなどを使用して実行できます(Javaドキュメントここ
)。
- マルチアップデートに$isolatedフラグを追加して、他の書き込み操作とインターリーブできないようにします。
アトミック性/分離に関する議論については、コメントも参照してください。マルチアップデートが分離されていると誤って想定していました。それらはそうではないか、少なくともデフォルトではありません。