2013-09-16 6 views
5

マルチプロセス環境でMongoDBを使用していますが、挿入順序でクエリをソートして、特定のドキュメントの後に挿入されるドキュメントに制限する方法が不思議でした。 1つのプロセスではObjectIDを使用できますが、そうでなければ同じ秒の異なるプロセスからの2つのObjectIdの順序が間違っている可能性があります。マルチプロセス環境での挿入順序によるMongoDBクエリのソートと制限

例:

ObjectId("5236dc5c 88ee6f 2075 bd0049") 

両IDのタイムスタンプ部分(5236dc5c)に等​​しいことプロセス2071 注右

ObjectId("5236dc5c 88ee6f 2071 f35fb8") 

前に、プロセス2075によって生成されたかもしれません。このタイムスタンプは秒単位で与えられます。

+0

これはプロセスIDをソートするので信頼できる方法ではありません。この例では、ソートを混乱させ、別のタイプの日付フィールドを格納する方がよいでしょう – Sammaye

答えて

3

挿入順序を確実にするには、独自の自動インクリメントシーケンスフィールドが必要です。唯一の楽観ループ本当に挿入順序は、シーケンス順序に等しいことを確認しない:ドキュメントが状態はありません注意する

  1. Counters Collection
  2. Optimistic Loop

一つのこと:これを実装するには2つの推奨方法があります。 。カウンターコレクションのアプローチは非常に可能ですが、インクリメントとドキュメントの挿入は2つの別々の操作であるため、理論的には保証されていません。

11

並べ替えにObjectIdまたは日付フィールドを使用すると、探している結果が得られない場合があります。挿入されたドキュメントのObjectIdと日付はクライアント側で生成されるため、複数のマシンからの接続で実行している場合、マシン間のタイミングが完璧でない限り、順序の不一致が発生します。

あなたは何をしようとしているかについてさらに詳しく説明できますか?特定のドキュメントの後に挿入されるドキュメントのリストが必要な理由によって、MongoDBから必要な動作を取得する方法はいくつかあります。

たとえば、そのような順序付けされたドキュメントのリストをキューとして使用しようとしている場合は、findAndModifyコマンドを使用して、未読ドキュメントを取得し、「読み取り」フィールドを原子的に更新して、それを2度読んでください。 findAndModifyを呼び出すたびに、読み取りフィールドがtrueに設定されていないコレクション内の最新の文書が検索され、そのフィールドがアトミックにtrueに設定され、処理のために文書がクライアントに返されます。

一方、実際には挿入された順序で文書のリストが必要な場合は、挿入された文書の自然順序付けを利用することができます。 MongoDBでは、文書のサイズや削除の変更によって物事を移動する必要がない限り、文書は挿入順にディスクに書き込まれます。自然順序付けを保つことが保証されているキャップ付きコレクションを使用することで、これを利用してドキュメントリストを手に入れることができます。キャッピングされたコレクションには、the documentationに記載されているいくつかの大きな制限があります。

+0

この詳細な回答ありがとうございます。システムの状態変化を追跡するサービスを実装する必要がありました。したがって、クライアントはこのサービスにアクセスして、何が変更されたかを尋ねることができます。あなたの最後の "状態"(状態コレクション内のエントリのObjectId)の何らかの種類の識別子が与えられたら、その後に起こったすべての変更を取得できるようにしたい(与えられたIDの後に挿入された状態コレクション内のすべてのドキュメント)。私は、すべてのユーザーに1つの状態コレクションを作成するなどのいくつかの欠点があるにもかかわらず、キャップ付きコレクションだけを解決する唯一の方法だと考えました。 – davidn

関連する問題