Elasticsearch でつまづいた話 (3)

今回のテーマはページング取得。

Query したときの件数

RDB の発想だと SQL select * from table したら全件取得されるのが当然だが Elasticsearch だと何も指定しなければ 10 件までしか取得されない。

size を指定するとこれを大きくできる。

{
   "size" : 100,
   "query" : { ... }
}

だが、この size にも上限がある。デフォルトだと 10,000 件だ ( _settings の index.max_result_window で定義されている) 。

作法としては Scroll API というのを使う。これは、ある時点でのスナップショットを保存して、取得しきれなかった分を辿っていくというものだ。

( From/Size でやろうとすると追加/削除があった場合に過不足が発生するので良くない)

クエリ文字列として scroll=hoge を渡す。 hoge1m など、スナップショットを保持する期間を指定する。

curl -XGET '[host]/_search?scroll=1m' -d '
{
   "size" : 100,
   "query" : { ... }
}'

レスポンスは以下のようになる。

{
   "_scroll_id" : "hogehoge",
   "hits" : { ... }
}

_scroll_id があるということは、取得しきれなかった分があることを意味する。続きを取得するには、以下のリクエストを送る。このときクエリを指定する必要はない。

curl -XGET '[host]/_search?scroll' -d '
{
   "scroll_id" : "hogehoge"
}'

このレスポンスにも続きがあれば新たな _scroll_id が返ってくるので、それを使って再び叩くことになる。

取得が完了したら、 DELETE でスナップショットを削除すると行儀がいい。

Aggregation 時もページングが必要になる場合があるが、その際はまたちょっと違った API を使うことになる。その話はまた今度。