前言
說明:本文章使用的ES版本是:6.7.0
git
在上一篇文章Elasticsearch如何建立索引?中,介紹了ES寫入文檔的過程。github
接下來咱們具體的看一下ES中,搜索過程是怎樣的算法
在ES中搜索
按照前面幾篇文章的步驟,咱們直接開始debug搜索的過程。上一篇文章中咱們寫入了以下的數據json
{
"id":6,
"title": "我是文件標題,可被搜索到66",
"text": "文本內容,ES時如何索引一個文檔的66",
"date": "2014/01/06"
}'
如今執行以下請求,對ES服務器發起搜索請求:緩存
curl -X GET 'localhost:9200/index_name/type_name/_search?pretty&q=title:66' -H 'Content-Type: application/json'
搜索能夠接收下面的形式的請求:服務器
客戶端
- 根據路由,RestSearchAction接收並開始處理請求
- RestSearchAction解析並驗證搜索參數,並將其封裝成SearchRequest,並指定服務端要處理該請求的Action:indices:data/read/search
服務端(master節點)
-
根據SearchRequest的index構造相應的ShardsIterator(分片迭代器),shardIterators由localShardsIterator(當前節點分片迭代器(默認一個節點上,一個索引有5個分片))和remoteShardIterators(其餘節點分片迭代器)合併而成,根據搜索條件,構建搜索策略。而後遍歷全部的shard。併發
-
搜索策略app
- 最多遍歷分片數量LONG最大值2^63-1
- 若是隻有一個分片,搜索類型只能是:QUERY_THEN_FETCH
- 是否查詢緩存
- 遍歷分片的最大併發數Math.min(256, Math.max(節點數, 1)*節點分片數),節點默認分片數:5
- 構造異步請求Action,將請求轉發到各個節點,等待回調
- 遍歷全部節點,構造節點查詢參數ShardSearchTransportRequest對象,對每一個節點執行查詢操做
- 執行查詢階段,首先在cache裏面判斷是否有緩存,若是有則執行緩存查詢;若是cache裏面沒有,執行QueryPhase類的execute()方法,他調用lucene的searcher.search對索引進行查詢,查詢成功回調onShardResult方法並返回docIds,查詢失敗回調onShardFailure(計數失敗狀況,並嘗試在副本分片上進行查詢)
- 查詢階段會計算文檔的相關性得分用於排序:
- Fetch階段:master接收到各個節點返回的docIds後,發起數據Fetch請求,經過docId和其分片ID到對應分片抓取數據,後合併數據返回給客戶端
大體的查詢時序邏輯:
curl
搜索總結
- Query階段能夠知道,一個搜索會遍歷這個索引下的全部分片,每一個分片都會執行一次搜索,並返回相同數量的文檔ID。好比搜索條件要查詢5條數據,有5個分片,則最終會查詢25條數據,排序後取前面5條數據
- 查詢和計算權重得分在Lucene完成,聚合是在ES中實現的
- 搜索會遍歷全部的分片,因此分片的數量影響着搜索的性能,而分片的數量也決定了ES能承載的最大數據量。因此在具體的應用中,須要在兩者之間選擇平衡
- 計算文檔權重得分,每搜索一次,都會根據搜索條件從新計算一次,對搜索性能影響很大
系列文章
- 搜索引擎ElasticSearch源碼編譯和Debug環境搭建
- 搜索引擎ElasticSearch的啓動過程
- Elasticsearch建立索引流程
- Elasticsearch搜索過程詳解
- Elasticsearch搜索相關性排序算法詳解
- Elasticsearch中的倒排索引