Scroll APIでpost filterを利用すると上手く結果が取得できない

こんにちは。

Elasticsearchのバージョン : 6.1.1

数万件のドキュメントがあるインデックスからScroll APIを利用して1,2万件程度のドキュメントを取得しようとしているのですが、絞り込みに以下のようなpost_filterを利用しています。

POST test_index/_search?scroll=1m
{
  "size": 2000,
  "post_filter": {
    "bool": {
      "must": [
        {
          "term": {
            "keyword_field": {
              "value": "hoge"
            }
          }
        }
      ]
    }
  }
}

上述のリクエストをした場合は正常に結果が取得できるのですが、その続きを取得しようとした場合に想定通りに取得できません。

POST /_search/scroll/
{
  "scroll" : "1m", 
  "scroll_id": "{_scroll_idの値を設定}"
}

想定では続きの2000件(sizeに指定した件数)が取得できると考えているのですが、hitsに返って来る件数が数件になっています。
そのまま続けてリクエストすると数件(リクエスト毎に異なる)だけ返って来て、hitsが空になった段階で取得できたドキュメントの総数は想定を下回っています。

Elasticsearchが5.6系の頃は上手くいっていたので絞り込み条件自体が誤っているということでは無いかなと思っております。

何かお分かりになることがあれば教えていただければ幸いです。

post_filterの代わりにqueryを利用した場合にはどうなるでしょうか?
また、queryを利用した場合に取得できるヒット件数は想定している約12000件であっていますでしょうか?

ちなみに、post_filterを利用している意図は何かありますでしょうか?

queryのfilterに置きかえれば正しく動作することは確認いたしました。
その場合は取得件数も想定通りです。

ですので置きかえれば問題ないのですが、6系へバージョンアップするにあたり
post_filterの挙動が変わるような記述を上手く見つけることが出来なかったため
こちらでお伺いさせていただいた次第です。

post_filterを使っているのは将来的にaggregationした結果から絞り込んで取得するかもしれないからという理由です。

なるほど。scrollはコストがかかるので、クライアントが多いなどの場合はちょっと懸念があるかと思ったので質問しました。

再現できるようなサンプルとかはお持ちでしょうか?
バグかもしれないので、再現できればIssueに登録していただけると助かります。

色々試してみて、以下のデータで再現できる事がわかりました。

Template

PUT _template/scroll_test_template
{
  "index_patterns": "scroll-test",
  "mappings": {
    "doc": {
      "properties": {
        "keyword_field": {
          "type": "keyword"
        }
      }
    }
  }
}

Document

POST scroll-test/doc/_bulk
{ "index": {} }
{ "keyword_field" : "value00000" }
{ "index": {} }
{ "keyword_field" : "value00001" }
{ "index": {} }
{ "keyword_field" : "value00002" }
   .
   .
   .
{ "index": {} }
{ "keyword_field" : "value49997" }
{ "index": {} }
{ "keyword_field" : "value49998" }
{ "index": {} }
{ "keyword_field" : "value49999" }

Query

GET scroll-test/_search?scroll=1m
{
  "size": 50,
  "post_filter": {
    "bool": {
      "must": [
        {
          "wildcard": {
            "keyword_field": "value*010*"
          }
        }
      ]
    }
  }
}

GET /_search/scroll/
{
  "scroll" : "1m",
  "scroll_id": "{_scroll_id}"
}

hitsのtotalは199となっているのですが、Scrollを呼び続けてhitsが空になった段階では合計で111件しか取得できませんでした。

scroll_id指定での呼び出し時にsizeの分だけ元のドキュメントを取得した上でpost_filterが適用され、その結果hitsが空になるとそこでScrollが終了しているような気がします。

とりあえずこちらの内容でIssueに登録してみようと思います。
ありがとうございました。

1 Like

確認ありがとうございます。
Issue登録で困ったことなどあれば連絡いただければと思います!

1 Like

Issue登録ありがとうございます。
リンクを貼っておきます。

すでにElasticsearchチームのものがPRを作成中です。

1 Like

こちらこそご確認いただき、ありがとうございました。
修正も早くて非常に助かります!

1 Like

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.