Elasticsearch でつまづいた話 (4)

前回に引き続きページング取得の話。

Aggregations でページング

Terms Aggregations したとき、キーが多すぎる場合に分割して取得したい。そんなときは Partition に区切って取得することになる。

{
   "size": 0,
   "aggs": {
      "aggregation_name": {
         "terms": {
            "field": "hoge",
            "include": {
               "partition": 0,
               "num_partitions": 10
            },
            "size" : 1000,
         }
      }
   }
}

この例では 10 分割にしている。 partition に 1〜9 を指定すると余りを取得することになる。注意したいのは、この例では 1000 件 × 10 partition で最後まで取得できる、と想定しているということだ。

推奨される流れとしては以下のとおり。

  1. Cardinality Aggregation でキーの数を測る

  2. キーの数に応じてチャンクの数 (上述の例でいう 10 ) を決める

  3. 各チャンクのサイズ (上述の例でいう 1000 ) を決める

  4. クエリする

更に述べておくと、各 Partition で取得される件数は、 Cardinality / num_partition に必ずしも一致しない。上述の例でいうと、毎回の取得件数は 1000 件より少なくなることがある (ふつうはその方が多い) 。集計結果が Partition をまたぐことがあるためだと思う。なので、 size の値は Cardinality / num_partition にすると取りこぼしが発生するので、それよりも大きい値 (2倍であれば十分、のはず...?) にしておくべきだ。