Elasticsearch 深入理解search After 處理深度分頁問題

深度分頁問題大致可以分爲兩類

  • 隨機深度分頁:隨機跳轉頁面
  • 滾動深度分頁:只能一頁一頁往下查詢

本文得search After 處理的是滾動深度分頁的問題

在舊版本中,ES爲深度分頁有scroll search 的方式,官方的建議並不是用於實時的請求,因爲每一個 scroll_id 不僅會佔用大量的資源(特別是排序的請求),而且是生成的歷史快照,對於數據的變更不會反映到快照上。這種方式往往用於非實時處理大量數據的情況,比如要進行數據遷移或者索引變更之類的。那麼在實時情況下如果處理深度分頁的問題呢?es 給出了 search_after 的方式,這是在 >= 5.0 版本才提供的功能。

這也是本文要重要講解的內容

基本思想:searchAfter的方式通過維護一個實時遊標來避免scroll的缺點,它可以用於實時請求和高併發場景。

🤔思考:那search After 爲什麼不用產生臨時快照之類的存儲信息,就能保證滾動順序讀取數據呢?

每個文檔具有一個唯一值的字段應該用作排序規範的仲裁器。否則,具有相同排序值的文檔的排序順序將是未定義的。建議的方法是使用字段_id,它肯定包含每個文檔的一個唯一值。

POST twitter/_search
{
    "size": 10,
    "query": {
        "match" : {
            "title" : "es"
        }
    },
    "sort": [
        {"date": "asc"},
        {"_id": "desc"}
    ]
}

返回出的結果信息 

{
      "took" : 29,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 5,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [
          {
            ...
            },
            "sort" : [
              ...
            ]
          },
          {
            ...
            },
            "sort" : [
              124648691,
              "624812"
            ]
          }
        ]
      }
    }

上面的請求會爲每一個文檔返回一個包含sort排序值的數組。這些sort排序值可以被用於 search_after 參數裏以便抓取下一頁的數據。比如,我們可以使用最後的一個文檔的sort排序值,將它傳遞給 search_after 參數:

GET twitter/_search
{
    "size": 10,
    "query": {
        "match" : {
            "title" : "es"
        }
    },
    "search_after": [124648691, "624812"],
    "sort": [
        {"date": "asc"},
        {"_id": "desc"}
    ]
}

注意:當我們使用search_after時,from值必須設置爲0或者-1。

search_after缺點是不能夠隨機跳轉分頁,只能是一頁一頁的向後翻,並且需要至少指定一個唯一不重複字段來排序。它與滾動API非常相似,但與它不同,search_after參數是無狀態的,它始終針對最新版本的搜索器進行解析。因此,排序順序可能會在步行期間發生變化,具體取決於索引的更新和刪除。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章