web-dev-qa-db-ja.com

Elasticsearch Scroll

Elasticsearchのスクロール機能は少し混乱しています。 elasticsearchでは、ユーザーが結果セットをスクロールするたびに検索APIを呼び出すことができますか?ドキュメントから

"search_type" => "scan",    // use search_type=scan
"scroll" => "30s",          // how long between scroll requests. should be small!
"size" => 50,               // how many results *per shard* you want back

つまり、30秒ごとに検索を実行し、レコードがなくなるまですべての結果セットを返すということですか?

たとえば、私のESは合計500レコードを返します。 ESからデータを取得し、それぞれ250レコードの2セットのレコードとして取得しています。最初に250レコードの最初のセットを表示し、ユーザーが250レコードの2番目のセットをスクロールしたときに表示する方法はありますか?

8
Devika

あなたが探しているのはページネーションです。

固定サイズを照会し、fromパラメーターを設定することにより、目的を達成できます。 250の結果のバッチで表示を設定したいので、size = 250を設定し、連続するクエリごとにfromの値を250ずつ増やします。

GET /_search?size=250                     ---- return first 250 results
GET /_search?size=250&from=250            ---- next 250 results 
GET /_search?size=250&from=500            ---- next 250 results

それどころか、Scan & scrollを使用すると、1回の検索で大量の結果セットを取得でき、理想的には、新しいインデックスへのデータの再インデックス付けなどの操作を目的としています。検索結果をリアルタイムで表示するために使用することはお勧めしません。

Scan & scrollを簡単に説明すると、基本的に、スキャン要求で提供されたクエリのインデックスをスキャンし、scroll_idを返します。このscroll_idを次のスクロール要求に渡して、結果の次のバッチを返すことができます。

次の例を検討してください-

# Initialize the scroll
page = es.search(
  index = 'yourIndex',
  doc_type = 'yourType',
  scroll = '2m',
  search_type = 'scan',
  size = 1000,
  body = {
    # Your query's body
    }
)
sid = page['_scroll_id']
scroll_size = page['hits']['total']

# Start scrolling
while (scroll_size > 0):
  print "Scrolling..."
  page = es.scroll(scroll_id = sid, scroll = '2m')
  # Update the scroll ID
  sid = page['_scroll_id']
  # Get the number of results that we returned in the last scroll
  scroll_size = len(page['hits']['hits'])
  print "scroll size: " + str(scroll_size)
  # Do something with the obtained page

上記の例では、次のイベントが発生します-

  • スクローラーが初期化されます。これは、結果の最初のバッチとscroll_idを返します
  • 後続のスクロールリクエストごとに、更新されたscroll_id(前のスクロールリクエストで受信)が送信され、結果の次のバッチが返されます。
  • スクロール時間は、基本的に検索コンテキストが維持される時間です。次のスクロール要求が設定された時間枠内に送信されない場合、検索コンテキストは失われ、結果は返されません。これが、膨大な数のドキュメントを含むインデックスのリアルタイム結果表示に使用すべきではない理由です。
11

scrollプロパティの目的を間違って理解している。 elasticsearchが30秒後に次のページデータを取得するという意味ではありません。最初のスクロールリクエストを行うとき、スクロールコンテキストを閉じるタイミングを指定する必要があります。 scrollパラメーターは、30秒後にスクロールコンテキストを閉じるように指示しています。

最初のスクロール要求を行った後、応答でscroll_idparameterを取得します。次のページでは、スクロール応答の次のページを取得するためにその値を渡す必要があります。 30秒以内に次のスクロール要求を行わない場合、スクロール要求は閉じられ、そのスクロール要求の次のページを取得できなくなります。

7
Ruben Vardanyan

ユースケースの例として説明したのは、実際には 検索結果のページ分割 です。これは、すべての検索クエリで使用可能で、結果は1万件に制限されています。 scrollリクエストを使用すると、その10kの制限を超える必要がある場合に必要です。scrollクエリを使用すると、ドキュメントのコレクション全体を取得することもできます。

おそらくここでの混乱の原因は、scrollの用語があいまいであることです。これは、クエリのタイプを意味し、そのようなクエリのパラメータの名前でもあります( 他のコメント)で述べたように 、次のスクロールチャンクを取得するまでESが待機する時間です。

scrollクエリは重いので、絶対に必要になるまで避けてください。実際、 docs には次のように書かれています:

スクロールはリアルタイムのユーザー要求ではなく、大量のデータの処理を目的としています...

あなたの別の質問について:

Elasticsearchでは、ユーザーが結果セットをスクロールするたびに検索APIを呼び出すことができますか?

はい、複数の パラレルスクロールリクエスト も可能です:

各スクロールは独立しており、スクロール要求と同様に並列処理できます。

6

エラスティックでのスクロールAPI のドキュメントもこの動作を説明しています。

結果サイズ10kはデフォルト値であり、必要に応じて実行時に上書きできます。

PUT { "index" : { "max_result_window" : 500000} }

スクロールIDの有効期間は、各スクロールリクエストでパラメータ「scroll」で定義されます。

..
  "scroll" : "5m"
  ..
0
m1k3ga