1

既存のデータベースからデータを消費しています。このデータベースには、システム イベントが格納されます。私のサービスは、タイマーでこのデータベースをチェックし、いくつかの新しいイベントが作成されたかどうかをチェックしてから、それをアップロードして処理する必要があります。単純なキューの実装のようなもの。

問題は、データベースをチェックするたびに新しいドキュメントを取得するにはどうすればよいかということです。イベントはさまざまなソースからデータベースに送信され、イベントの順序がないため、タイムスタンプを使用できません。したがって、挿入順序のみを使用する必要があります。

4

2 に答える 2

5

いくつかのオプションがあります。

最初の、そしてユース ケースに一致する場合に最も簡単な方法は、キャップ付きコレクションを使用することです。capped コレクションは、一種のリング バッファとして機能する事前定義されたサイズのコレクションです。コレクションがいっぱいになると、ドキュメントの上書きが開始されます。コレクションを反復処理するには、「tailable」カーソルを作成するだけで、「最後に処理されたドキュメント」を特定する方法が必要になります (ドキュメント内の単純な「完了」フラグでも機能しますが、ドキュメントが挿入されたときに存在する必要があります)。 . ドキュメントをまったく変更できない場合は、最後に処理したドキュメントをどこかに保存し、コース タイム スタンプを使用して (開始位置を概算し)、さらにドキュメントを処理する前に最後のドキュメントを探すこともできます。

このソリューションの唯一の問題は、コレクションに書き込むことができるドキュメントの数が制限され、時間の経過とともに増加しないことです。ドキュメントに対して実行できる書き込み操作には制限がありますが (サイズが大きくなることはありません)、ドキュメントを変更しているようには見えません。

より複雑な 2 番目のオプションは、oplog を使用することです。スタンドアロン構成の場合は、oplog を作成して使用するために -replSet オプションを渡す必要があります。oplog を構成しないだけです。分割構成では、各「レプリカ セット」を個別に追跡する必要があります。oplog には、サーバー上のすべてのコレクション/ドキュメントに対して行われた各挿入、更新、削除のドキュメントが含まれています。各エントリには、タイムスタンプ、操作、および ID (少なくとも) が含まれます。それぞれの例を次に示します。

入れる

{ "ts" : { "t" : 1362958492000, "i" : 1 }, 
  "h" : NumberLong("5915409566571821368"), "v" : 2, 
  "op" : "i", 
  "ns" : "test.test", 
  "o" : { "_id" : "513d189c8544eb2b5e000001" } }

消去

{ ... "op" : "d", ..., "b" : true, 
   "o" : { "_id" : "513d189c8544eb2b5e000001" } }

アップデート

{ ... "op" : "u", ..., 
  "o2" : { "_id" : "513d189c8544eb2b5e000001" }, 
  "o" : { "$set" : { "i" : 1 } } } 

タイムスタンプはサーバー上で生成され、単調に増加することが保証されています。これにより、関心のあるドキュメントをすばやく見つけることができます。

このオプションは最も堅牢ですが、一部の作業が必要です。

コレクションに「ウォッチャー」を作成するためのデモ コードをいくつか書きました。そのコードはGitHubにあります。具体的には、com.allanbank.mongodb.demo.coordinationパッケージのコードを見てください。

HTH、ロブ

于 2013-03-12T01:42:26.313 に答える
1

_id が ObjectId 型の場合、実際にタイムスタンプを使用できます。

prefix = Math.floor((new Date( 2013 , 03 , 11 )).getTime()/1000).toString(16)
db.foo.find( { _id : { $gt : new ObjectId( prefix + "0000000000000000" ) } } )

このように、イベントのソースがいつどこにあったかは関係ありません。重要なのは、ドキュメントの挿入が記録されたときだけです (以前のタイマーよりも高い)。

もちろん、スキーマレスであり、isNew などのフィールドをいつでも true に設定したり、クエリ/カーソルと組み合わせて false に設定したりできます。

于 2013-03-11T00:41:26.117 に答える