1

私の Google App Engine アプリでは、サービス呼び出しの GET リクエストに応答して、データストア クエリから潜在的に多数のエンティティを取得して返す必要があります。この呼び出しは、潜在的に数千のエンティティと MB のシリアル化されたデータを返す可能性があります。

応答パケットの最初の部分は、シリアル化された結果に含まれるエンティティの数を伝え、その後にすべてのシリアル化されたエンティティが続きます。現在、クエリ内のすべてのエンティティをQueryResultIterator最大ページ サイズ制限まで反復処理しています。その後、カーソルを返します。このカーソルを使用して、前の呼び出しが中断された場所からフェッチを続行できます (最大値に達し、それでもクエリが返されます)。結果を反復処理しながら、それらをリストに保存します。クエリ結果を使い果たすか、最大ページ サイズに達すると、このリストのサイズからエンティティの数を取得できます。しかし、このリストをもう一度反復処理して各エンティティをシリアル化し、結果を応答出力ストリームに書き込む必要があります。

これがこの操作を実行する最も効率的な方法かどうかはわかりません。実際にすべてを反復処理するか、リストに直接フェッチする前に、クエリの結果のエンティティの数を取得する方法はありますか? (リストメソッドはとにかく機能しません。これは、QueryResultIterator を使用する必要があるカーソルを使用しているためです)。

QueryResultIteratorメソッドがありgetIndexList()ます。これは、クエリの結果に含まれるエンティティの数を取得するための低コストの方法でしょうか? このリストには、クエリの結果のエンティティごとに正確に 1 つのインデックス オブジェクトが含まれると想定しています。また、このリストには、インタレータの現在のカーソル位置の後のエンティティのインデックスのみを含める必要があります。私の理解は正しいですか、それともこの方法は私が思っていることをしませんか?

インデックスだけのリストは、エンティティ全体のリストをロードするよりもはるかに少ないメモリを必要とします。ただし、このリストがクエリのプリフェッチまたはチャンク サイズによってまったく制限されるかどうか、またはクエリの limit パラメータを使用する必要があるかどうかはわかりません。最大ページ サイズに 1 を加えたサイズまでの結果 (まだ結果があることを知り、続行するためのカーソルを提供するため)。

現在、プリフェッチとチャンク サイズを (ページ制限のサイズに) 設定していますが、代わりにカーソルを使用しているため、制限またはオフセット パラメータは使用していません。私が理解していることから、カーソルはオフセット/制限よりも望ましいです。limit パラメーターを設定すると、カーソルを使用したクエリの続行に影響しますか?

明らかに、GAE データストア クエリがどのように機能し、パラメータの変更によってどのように影響を受けるかについて、かなりの数の質問があります。したがって、どんな洞察も高く評価されます。App Engine API のドキュメントは、多くの場合、メソッド シグネチャから推測できるほとんどの内容をメソッドの 1 つの文で説明しているように、まばらです。それ以外の場合は、通常、あまり詳細には触れません。結局、今のやり方でいいのかもしれません。そのままで動作しますが、サービス呼び出しを最適化して、クライアント アプリケーションで可能な限り最高の応答時間を取得しようとしています。

更新:ところで、私は自分のアプリでObjectify v3 を使用しており、このクエリを実行しています。地理位置クエリ ( geomodelを使用) や投影クエリ (Objectify v3 ではサポートされていません) を実行するなど、低レベルのデータストア API を使用する必要がある場所がいくつかあります。したがって、Objectify を使用してこれを行う良い方法があれば、それが理想的です。それ以外の場合は、低レベル API を使用できますが、この方法では常に面倒です。

4

2 に答える 2

5

低レベル API と Objectify の両方に count() メソッドがあります (詳細については、javadoc を参照してください)。ただし、カウントは非常に高価で時間のかかる操作になる可能性があります。返される数値ごとに 1 つの小さな操作が必要です。たとえば、count() が 5000 を返すと、5000 回の小さな ops (さらにクエリの 1 回の読み取り) がかかり、5000 回すべてのキーのみのスキャンを実行するのと同じくらいの時間がかかります (これは GAE が実際に行うことです)。

絶対に正確なカウントが必要な場合は、(おそらくシャードされた) カウンターをインクリメント/デクリメントして、この値を自分で集計する必要があります。フィルタリングされたクエリを扱う場合、これは非常に厄介です。

ここには、唯一の正解はありません。Google 検索では、「約 1 億 1900 万件の結果」のような合計が表示されますが、これは意図的に不正確であり、ほぼ確実に事前に計算されています。結果セットが小さい場合は、count() を使用してもかまいませんが、銀行を壊さないように limit() を適用することをお勧めします。いつでも「500 件以上の結果...」と言うことができます。

于 2013-06-13T15:02:11.060 に答える
1

次のコードを使用できるよりもレコードの数を取得したい場合

  com.google.appengine.api.datastore.Query qry = new com.google.appengine.api.datastore.Query("EntityName");
  com.google.appengine.api.datastore.DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService();
  int totalCount = datastoreService.prepare(qry).countEntities(FetchOptions.Builder.withDefaults());

anf 使用できるよりもフィルターが必要な場合

qry.addFilter("firstName", FilterOperator.EQUAL, firstName);

それがあなたを助けることを願っています

于 2013-06-10T14:04:21.367 に答える