2016-10-21 15 views
0

私が取り組んでいるMongoDBのコレクションは、携帯電話からセンサーデータを受け取り、2〜6秒ごとにサーバーにpingされます。16MB以上の文書に対するMongoDBの回避策?

データが巨大で、4時間から5時間後に16Mbの限界を超えてしまったため、これには何の問題もありません。

私はスタックオーバーフローでそれを検索しようとしましたが、さまざまな質問をしましたが、誰も実際にハックを共有しませんでした。

DB側では、gridFS経由で大きなファイルを処理するようなチャンクを配布する方法はありますか?

+2

ドキュメントを役に立てば幸いアンチパターンです。あなたのユースケースをより良くサポートするために、おそらくデータモデルを再考するべきです。 GridFSアプローチは、大きなバイナリブロブを格納する場合にのみ適しています。これは、クエリーを行う予定のフィールドを持つデータには役に立ちません(クエリーがGridFSのバイナリファイルに関するメタデータに限定されていない限り)。スキーマの推奨事項については、サンプルドキュメントを投稿し、一般的なアップデートとクエリを記述する必要があります。 MongoDBサーバーのバージョンと構成されたストレージエンジンも関連します。 – Stennie

答えて

0

MongoDBでGriFSを使用してこのような状況を処理できます。

の代わりに単一のドキュメントにファイルを格納する別の文書として各チャンクを、GridFS部品にファイルを分割し、またはチャンク1、格納します。デフォルトでは、GridFSは255KBのチャンクサイズを使用します。つまり、最後のチャンクを除いて、GridFSは255 KBのチャンクにファイルを分割します。最後のチャンクは必要なだけの大きさです。同様に、チャンクサイズよりも大きくないファイルは、必要なだけのスペースと追加のメタデータを使用して最終的なチャンクを作成します。

GriFSのドキュメントには、GridFSを実装するために必要なものがほとんどすべて含まれています。あなたはそれに従うことができます。 (エラーが発生した場合、エラーオブジェクト - あなたのデータをストリームであるため

、あなたは

gs.write(data, callback) 
データがバッファや文字列である

は、コールバックは2つのパラメータを取得します...次のように試すことができます)と、書き込みが成功したかどうかを示す結果値。 GridStoreが閉じていない間は、すべての書き込みが開いたGridStoreに追加されます。

ストリーミング関連の情報については、github pageに従うことができます。

+0

データは1〜2秒ごとにpingされるため、バッファリングしてファイルを作成すると、プロセスが妨害され、アプリケーションからサーバーへのペイロードが問題になります。 – DeathNote

+0

あなたのデータはストリームとして送られますか? – gypsyCoder

+0

はい、ソケット経由。 – DeathNote

4

この問題を解決するには、データ構造を少し修正する必要があります。その音によって、文書が16MBの制限を超えるためには、センサデータを1つの文書の配列に埋め込む必要があります。

私はここでGridFを使用することを推奨しませんが、私はそれが最良の解決策であるとは信じません。

バケツとして知られている技法があります。これは本質的にセンサの読みを別々のドキュメントに分割して、この問題を解決します。

それが動作する方法をされて、私はこのようになります特定のセンサのためのいくつかの組み込みの測定値との文書を持って言うことができます:上記の構成によると

{ 
    _id : ObjectId("xxx"), 
    sensor : "SensorName1", 
    readings : [ 
     { date : ISODate("..."), reading : "xxx" }, 
     { date : ISODate("..."), reading : "xxx" }, 
     { date : ISODate("..."), reading : "xxx" } 
    ] 
} 

、大きな欠陥がすでに存在し、測定値配列が指数関数的に増加し、16MBのドキュメントの制限を超える可能性があります。

は、だから我々は何ができるのか、このように見えるようにカウントプロパティが含まれるように、わずかな構造を変更です:あなたは$あなたの埋め込まれた配列にあなたの読書を押すと

{ 
    _id : ObjectId("xxx"), 
    sensor : "SensorName1", 
    readings : [ 
     { date : ISODate("..."), reading : "xxx" }, 
     { date : ISODate("..."), reading : "xxx" }, 
     { date : ISODate("..."), reading : "xxx" } 
    ], 
    count : 3 
} 

この背後にある考え方は、あなたは、あります実行されるすべてのプッシュに対してcount変数をインクリメント($ inc)します。この更新プログラム(プッシュ)操作を実行するときに、あなたは「アップサート」を設定することができるように、あなたの更新オプションを設定し、その後

このような
{ count : { $lt : 500} } 

をsomrthing見えるかもしれない、プロパティを「カウント」は、この上のフィルタが含まれます=真:

db.sensorReadings.update(
    { name: "SensorName1", count { $lt : 500} }, 
    { 
     //Your update. $push your reading and $inc your count 
     $push: { readings: [ReadingDocumentToPush] }, 
     $inc: { count: 1 } 
    }, 
    { upsert: true } 
) 

はMongoDBのアップデートとアップサート・オプションの詳細はこちらを参照してください。

MongoDB update documentation

何が起こるだろうことは、ありますフィルター条件が満たされていない場合、このセンサーに既存の文書がないか、または項目がプッシュされるたびにカウントが増えているため、カウントが500以上になると、新しい文書が作成され、読み取り値はこの新しい文書に埋め込まれます。したがって、これを正しく行うと、16MB制限に達することはありません。

データベースに特定のセンサーの読み取り値を問い合わせると、そのセンサーの読み取り値が1つではなく、そのセンサーの複数の文書を返すことができます(たとえば、読み取り値が10,000の場合など)。 20の文書を取得し、それぞれにそれぞれ500の読みがあります。

次に、集計パイプラインと$ unwindを使用して、読んだものを独自の個別ドキュメントのようにフィルタリングできます。ここを参照してくださいアンワインドの詳細については

が、それは非常に便利です

MongoDB Unwind

私は、これは無限の成長に

関連する問題