web-dev-qa-db-ja.com

大きなJSONファイルを読み取り、マップのサブセットを返す

どちらの方向に移動すればよいかわからないため、これはある程度広い問題です。マップにマーカーを表示するために Polymaps を使用しています。マーカーは静的ですが、視覚化は入力データの値に依存します。地図のために私はこのようなデータを読みました:

    var b = read_function("data.json", function(a) {
        json_object = a
    });

    map.add(b.on("load",load))

これは、JSONファイルが比較的小さい場合にうまく機能します。サイズが30 MBを超えると、ブラウザが文句を言い始めます(遅い、クラッシュするなど)。私は数値気象予測(NWP)モデルデータを使用しているので、主にFortranとPythonを使用しており、表示できるデータは130万ポイントのモデルドメイン全体のものです。これは130万のマーカーです。このすべてのデータを含むJSONファイルは、1.1 GBを占めます。

確かに、このファイルを一度に読むのは賢明ではなく、とにかくすべてのマーカーを同時に表示したくありません。マーカーの密度は、ズームが低いとはるかに低くなり、ズームインするにつれてますます表示されます。

だから私の質問は、アマチュアはどのように進むべきですか?マップの状態に応じて、より小さなJSONオブジェクトを返すAPIを何らかの方法で作成する必要がありますか?

3
Whir

JSONファイルは変更されないため、1回前処理してマーカーの位置を抽出し、特定の目的に最適化されたファイル形式で保存するのに理想的な候補です。

ここで2つの異なる問題を解決する必要があります。

  • 異なるズームレベル(「詳細レベル」)ごとに異なる密度のマーカーの個別のセットを作成します。難しいことではありません。ズームレベルごとに巨大なJSONファイルを1回処理し、保持するマーカーと破棄するマーカーを決定して、これらのマーカーを正確に含む新しいJSONファイルを作成します。

    このタスクの最適化されたソリューションについては、「貧しい人々の空間インデックス」を使用します。特定のズームレベルで、サイズが10x10mのすべてのタイルに1つ以下のマーカーが必要だとします。次に、各マーカーの座標ペア(X、Y)を次の10メートルの倍数に丸め、丸められた座標ペアを、最大でキーごとに1つのエントリを持つマーカーの辞書のキーとして使用します。

  • 特に高レベルの詳細を必要とするズームレベルの場合、マーカーを一度にロードして描画する必要がないという考えは、セット全体を特定のサイズのタイルに分割し、タイルごとに1つのファイルを使用することです(通常、タイルの左上の座標)。マーカーの一部のみが表示されている場合は、関連するタイルのみをディスクから読み込んでブラウザーに表示できます。

    私はポリマップの専門家ではありませんが、マニュアルをざっと見てみると、まさにこの種のタイルデータ編成をサポートしているようです。つまり、これがそのlibのマニュアルに飛び込んで、 これ のような例を検討し始め、同様の何かを実装する必要があるポイントです(そして「1」とは、「あなた」という意味です- ;-))。これを真剣に試した後、問題が発生した場合に備えて、Stackoverflowで特定のコーディング問題について質問することをお勧めします。

5
Doc Brown

FortranとPythonは、数値を計算するための優れたツールであり、一度にすべてのマーカーを表示したくない場合は、入力に基づくいくつかの「フィルター」ルールがあります。 、そうですか?おそらく、一度にメモリにロードしないことでファイルを読み取ることができるストリームまたはバッファを持っています。

入力または「入力の範囲」に基づいてJSONマーカーファイルを一括で分割できるように、大まかな前処理を行ってみませんか?

私はこの処理を「オフライン」で行うことについて話しているので、「ズーム」値の範囲とそれぞれに含まれるポイントを大まかに知っているとしましょう。

次のようなマップまたは関連リストを作成できます。

  • 1〜5のズームレベル:JSON([この範囲に対応するポイントのリスト])
  • 6と8の間:JSON([filtered list])
  • 8より大きい:JSON([残りのリスト])

したがって、ズーム3を使用している場合、最初のカテゴリに分類され、2番目のズームは8に分類されます。

該当する最初のバケットのリストルックアップは簡単に作成できます。これらのリストが大きくなる場合、リストに開始と終了がある場合、ルックアップはO(1)のみであり、次に、前処理されたリストを操作することです。

たぶん、これはあなたにどのように進めるかについていくつかの考えを与えることができます。

1
Bruno Oliveira

まず、@ DocBrownの全体的なアプローチが気に入っています。ただし、おそらくもっと単純なものについては、データが次のように見える場合

[
  {
    point 1 data
    {
       possible with nested stuff BUT without any 
      "some field name{" : " some } data" 
       that include brackets to screw up simple counting of brackets
    } 
  },
  ...
  { 
    point 1,300,000
  }
]

単純な解析コードを記述して、一度に{...}ブロック内の1つのポイントを取得し、解析することができます。したがって、低いズームレベルでは、最初の100程度を取得して表示します。ユーザーがズームインすると、ファイルをさらに読み、より多くのポイントを表示します。一度に数行だけファイルを読み取っているので、ファイルI/Oからのメモリの問題はありません。 (私は願います)

1
user949300