2017-06-20 8 views
0

私は10000+レコードを返すmongo DBクエリを持っています。ビジネスサービスでは、GSON(Google JSON)形式でレコードを返します。以下はコードスニペットです。google.gson.JsonArray形式のMongoDBから大きなデータセットを返す効果的な方法

 String mongoClientURI = null; 
     mongoClientURI = "mongodb://" + dbUser + ":" + pwd + "@" + host + ":" + port + "/" + databaseName; 


     MongoClient client = new MongoClient(new MongoClientURI(mongoClientURI)); 
     MongoDatabase db = client.getDatabase(databaseName); 

     // Find query returns more than 10K records 
     FindIterable<Document> dbResult = db.getCollection("mycollection").find(); 

     // This line takes too much time & CPU  
     List<Document> result = getDocumentArray(dbResult); 

     // This line takes too much time & CPU 
     JsonArray finalResult = getJSONArray(result); 

    public static List<Document> getDocumentArray(FindIterable<Document> input) { 
     List<Document> output = new ArrayList<Document>(); 
     for (Document doc : input) { 
      output.add(doc); 
     } 
     return output; 
    } 

    public static JsonArray getJSONArray(Iterable<Document> docs) { 
     JsonArray result = new JsonArray(); 
     if (docs == null) { 
      return result; 
     } 

     for (Document doc : docs) { 
      JsonObject jsonObject; 
      JsonParser parser = new JsonParser(); 
      try { 
       jsonObject = parser.parse(doc.toJson()).getAsJsonObject(); 
       result.add(jsonObject); 
      } catch (Exception e) { 
       System.out.println(e.getMessage()); 
      } 
     } 
     return result; 
    } 

問題はフェッチとGSONアレイへのMongoDBのデータのconvesionをしながら、それは時間とCPUサイクルがかかるです。誰でもmongodbからgson形式に大きなデータセットをフェッチする効果的な方法は何ですか?

は、一般的に私の周り10K、20Kへの記録、(50K max)を取得します。私はそれらのすべてを返す必要があります。私のUIコンポーネントでは、データをレンダリングするためには、すべてのレコードが必要です。一般の人々は、したがって、それは一度にあまりにも多くのレコードを持っていませんが、私の場合、私は&は、オンザフライでのオブジェクトのクラスタを作成し、すべてのレコードを取るマップコンポーネントを持って、ページングとデータグリッドを使用します。

ご協力いただければ幸いです。

アトゥールSureka

+0

この結果を組み合わせてみてください任意のタイプのメモリ内オブジェクト表現ではなくストリームへの書き込みあなたの質問はもちろん、すべてをデータベースコレクションにダンプするよう求めています。ストリームを使用し、メモリにロードしないでください。 –

答えて

1

効果的な方法は、一度にすべての文書を返し、ページングを実装する代わりにskip()limit()機能を使用しないだろう。あなたのコレクションはのは、万枚の書類を言わせている場合は、メモリ内の大規模なListで終わるだろうとあなたも一度にUI上のすべての文書を表示する必要がない場合があります。ここで

あなたはページングを実装することができます方法は次のとおりです。

1st Call : db.getCollection("mycollection").find().limit(10); 
2nd Call : db.getCollection("mycollection").find().skip(10).limit(10); 
3rd Call : db.getCollection("mycollection").find().skip(20).limit(10); 

skipは、ページあたりlimitドライブの項目に対し、ページ番号を駆動します。 sortも使用して、注文書(here'sのドキュメント)を定義することができます。

別のアプローチは、cursorにすべての文書をスクロールして、キュー/クライアントにプッシュするキューイングメカニズムやストリーミングを使用することです。

更新

これは、あなたがより速く、既存の実装を作るために何ができるかです:

  • thisを見てみましょう(速い文書を処理するためにparallelStreamIterable変換SO再どのように答えます
  • は、各ドキュメントのJsonParserインスタンスを作成しないでくださいIterablestreamに変換します。インスタンスを一度作成し、すべてのドキュメントに使用します。アプリケーション
+0

あなたの応答をありがとう、私はページングを理解していますが、私は一度にすべてのレコードが必要です - 私はデータテーブルを持っていない、代わりに私はマップ上のデータを表示する必要があります。すべてのデータをクライアント上のクラスタを作成するマップコンポーネントに渡す必要があります。 –

+0

さて、UIは、さまざまなページングパラメータを使用してサービスに複数の呼び出しを行い、すべてのレコードを取得できます。 10000レコードを表示する場合は、10個の要求を並行して実行して戻ることができます。そうでない場合は、 'json'文書全体をUIにダンプするのではなく、' find'で必須フィールドだけを選択する方法もあります。 –

+0

私はそれを試みますが、あなたはJOLT https://github.com/bazaarvoice/joltが私の問題を解決するかもしれないと思いますか? –

0

ため

  • 増加Xmx値は、MongoDBの中の列に索引を追加することがありますか?クエリをより速く取得/読み込むのに役立ちます。デフォルトの索引は_id列にあります。あなたが一定の基準に基づいて発見するため

    別の方法があり、2

    db.getCollection("mycollection").find({ dept: "grocery", category: "chocolate" }); 
    db.getCollection("mycollection").find({ dept: "sales", category: "honey" }); 
    

    にこれを分割したデータの選択は、あなたのは次のようになり、実際にその大きさである場合には、後に

  • +0

    お返事ありがとうございます。 - 私はfindにパラメータを渡すつもりはありません。 –

    +0

    私は知っている..しかし、部門、カテゴリはparamtersではない..彼らは列名です。あなたの列にいくつかのインデックスを入れましたか? –

    +0

    すでにインデックスを作成しようとしましたが、違いはありませんでした。 –

    関連する問題