Elasticsearch混合搜索深度解析(下):執行機制與完整流程

引言

在上篇中,我們發現了KNN結果通過SubSearch機制被保留的關鍵事實。本篇將繼續深入分析混合搜索的執行機制,揭示完整的處理流程,并解答之前的所有疑惑。

深入源碼分析

1. SubSearch的執行機制

1.1 KnnScoreDocQueryBuilder的實現

KNN結果被轉換為KnnScoreDocQueryBuilder,這個類負責在查詢階段重新執行KNN搜索:

// server/src/main/java/org/elasticsearch/index/query/KnnScoreDocQueryBuilder.java
public class KnnScoreDocQueryBuilder extends AbstractQueryBuilder<KnnScoreDocQueryBuilder> {private final String field;private final List<ScoreDoc> scoreDocs;@Overrideprotected Query doToQuery(SearchExecutionContext context) throws IOException {// 創建KnnScoreDocQuery,包含DFS階段找到的文檔ID和分數return new KnnScoreDocQuery(field, scoreDocs);}
}
1.2 KnnScoreDocQuery的核心邏輯
// 簡化版的KnnScoreDocQuery實現
public class KnnScoreDocQuery extends Query {private final String field;private final List<ScoreDoc> scoreDocs;@Overridepublic Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) {return new Weight(this) {@Overridepublic Scorer scorer(LeafReaderContext context) {// 只對DFS階段找到的文檔進行打分return new KnnScoreDocScorer(this, context, scoreDocs);}};}
}

2. 分數計算與合并機制

2.1 主查詢分數計算

主查詢對10000+文檔進行打分,然后應用boost:

// 主查詢分數計算
float queryScore = calculateQueryScore(document);
float finalQueryScore = queryScore * 0.05; // 應用boost
2.2 KNN分數計算

KNN SubSearch只對50篇候選文檔進行打分:

// KNN分數計算
float knnScore = calculateKnnScore(document);
float finalKnnScore = knnScore * 1.0; // 應用boost
2.3 分數合并邏輯

通過OR邏輯合并所有文檔的分數:

// 分數合并邏輯(簡化版)
Map<String, Float> finalScores = new HashMap<>();// 處理主查詢結果
for (ScoreDoc scoreDoc : queryResults) {String docId = getDocId(scoreDoc);float score = scoreDoc.score * 0.05;finalScores.put(docId, score);
}// 處理KNN結果
for (ScoreDoc scoreDoc : knnResults) {String docId = getDocId(scoreDoc);float score = scoreDoc.score * 1.0;// OR邏輯:取最大值if (finalScores.containsKey(docId)) {finalScores.put(docId, Math.max(finalScores.get(docId), score));} else {finalScores.put(docId, score);}
}

3. Filter的影響路徑

3.1 Filter的傳遞過程

KNN的filter通過以下路徑傳遞到向量搜索:

// KnnVectorQueryBuilder.java
public class KnnVectorQueryBuilder extends AbstractQueryBuilder<KnnVectorQueryBuilder> {private final String field;private final float[] queryVector;private final int k;private final int numCandidates;private final QueryBuilder filter; // 關鍵:filter字段@Overrideprotected Query doToQuery(SearchExecutionContext context) throws IOException {Query filterQuery = null;if (filter != null) {filterQuery = filter.toQuery(context);}// 創建KnnVectorQuery,傳入filterreturn new KnnVectorQuery(field, queryVector, k, numCandidates, filterQuery);}
}
3.2 向量搜索中的Filter應用
// DenseVectorFieldMapper.java 第903行
case FLOAT -> parentFilter != null? new DiversifyingChildrenFloatKnnVectorQuery(name(), queryVector, filter, numCands, parentFilter): new KnnFloatVectorQuery(name(), queryVector, numCands, filter);

Filter直接限制向量搜索的候選文檔范圍,這就是為什么KNN的filter會影響最終結果的原因。

完整執行流程圖

時序圖

客戶端ElasticsearchDFS階段DfsQueryPhase主查詢執行KNN查詢執行分數合并發送混合搜索請求開始DFS階段執行KNN查詢(應用filter)返回top 50候選文檔DFS階段完成開始DfsQueryPhaseKNN結果轉換為SubSearchDfsQueryPhase完成執行主查詢對10000+文檔打分×0.05主查詢完成執行KNN SubSearch對50文檔打分×1KNN完成分數合并OR邏輯合并所有分數合并完成最終排序和分頁返回前50條結果客戶端ElasticsearchDFS階段DfsQueryPhase主查詢執行KNN查詢執行分數合并

數據流圖

混合搜索請求
DFS階段
KNN查詢執行
向量搜索
應用filter
返回top 50
DfsKnnResults
DfsQueryPhase
轉換為SubSearch
KnnScoreDocQueryBuilder
主查詢執行
對10000+文檔打分
應用boost 0.05
KNN SubSearch執行
對50文檔打分
應用boost 1
分數合并
OR邏輯合并
最終排序
應用from/size
返回結果

關鍵問題解答

問題1:KNN結果是否被丟棄?

答案: 不會。KNN結果通過SubSearch機制被保留在最終查詢中。

問題2:Filter如何影響結果?

答案: Filter直接影響向量搜索的候選范圍,限制KNN只在滿足條件的文檔中搜索。

問題3:分數如何合并?

答案: 通過OR邏輯合并,取每個文檔的query分數×0.05和knn分數×1的最大值。

問題4:from/size的作用?

答案: 在最終分數排序后應用,選取總分最高的前50篇文檔。

性能優化建議

1. 參數調優

1.1 num_candidates優化
{"knn": {"field": "q_vec","k": 50,"num_candidates": 100  // 根據數據量調整}
}
  • 小數據集: num_candidates = k * 2
  • 大數據集: num_candidates = k * 10
  • 性能與精度平衡: 根據實際需求調整
1.2 boost值調優
{"query": {"bool": {"boost": 0.05  // 根據業務需求調整}},"knn": {"boost": 1.0  // 根據業務需求調整}
}

2. 索引優化

2.1 向量索引優化
{"mappings": {"properties": {"q_vec": {"type": "dense_vector","dims": 768,"index": true,"similarity": "cosine"}}}
}
2.2 文本字段優化
{"mappings": {"properties": {"title_tks": {"type": "text","analyzer": "standard","search_analyzer": "standard"}}}
}

3. 查詢優化

3.1 Filter優化
{"knn": {"filter": {"bool": {"must": [{"term": {"category": "research"  // 使用精確匹配}}]}}}
}
3.2 字段權重優化
{"query_string": {"fields": ["title_tks^10",      // 標題權重最高"important_kwd^30",  // 關鍵詞權重最高"content_ltks^2"     // 內容權重較低]}
}

監控與調試

1. 查詢性能監控

{"query": {...},"knn": {...},"profile": true  // 啟用查詢分析
}

2. 分數調試

{"query": {...},"knn": {...},"_source": false,"explain": true  // 啟用分數解釋
}

總結

通過深入源碼分析,我們完全理解了Elasticsearch混合搜索的執行機制:

關鍵發現

  1. KNN結果不會被丟棄: 通過SubSearch機制保留
  2. Filter直接影響向量搜索: 限制候選文檔范圍
  3. 分數通過OR邏輯合并: 取query和knn分數的最大值
  4. boost值影響最終排序: 0.05 vs 1.0的權重差異

執行流程

  1. DFS階段: KNN查詢執行,返回候選文檔
  2. DfsQueryPhase: KNN結果轉換為SubSearch
  3. 主查詢執行: 獨立執行query和knn sub_search
  4. 分數合并: 通過OR邏輯和boost值合并分數
  5. 最終排序: 按總分排序并應用分頁

實際應用

這個理解幫助我們:

  • 正確配置混合搜索參數
  • 優化查詢性能
  • 調試查詢問題
  • 設計更好的搜索策略

經驗總結

1. 源碼分析的價值

直接查看源碼是理解復雜系統的最佳方式,比文檔更準確、更深入。

2. 系統性思維的重要性

不能孤立地看某個組件,要理解整個系統的協作機制。

3. 實踐驗證的必要性

理論認知需要通過實際測試來驗證,避免被表面現象誤導。

4. 持續學習的態度

技術不斷發展,要保持好奇心和學習熱情。

參考資料

  • Elasticsearch 8.11 源碼
  • server/src/main/java/org/elasticsearch/action/search/DfsQueryPhase.java
  • server/src/main/java/org/elasticsearch/search/SearchService.java
  • docs/reference/search/search-your-data/knn-search.asciidoc
  • Lucene 向量搜索文檔

本文檔基于Elasticsearch 8.11源碼分析,如有疑問或發現錯誤,歡迎討論交流。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/914138.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/914138.shtml
英文地址,請注明出處:http://en.pswp.cn/news/914138.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Apache HTTP Server 從安裝到配置

一、Apache 是什么&#xff1f;Apache&#xff08;全稱 Apache HTTP Server&#xff09;是當前最流行的開源Web服務器軟件之一&#xff0c;由Apache軟件基金會維護。它以穩定性高、模塊化設計和靈活的配置著稱&#xff0c;支持Linux、Windows等多平臺&#xff0c;是搭建個人博客…

php中調用對象的方法可以使用array($object, ‘methodName‘)?

是的&#xff0c;在PHP中&#xff0c;array($object, methodName) 是一種標準的回調語法&#xff0c;用于表示“調用某個對象的特定方法”。這種語法可以被許多函數&#xff08;如 call_user_func()、call_user_func_array()、usort() 等&#xff09;識別并執行。 語法原理 在P…

【設計模式】單例模式 餓漢式單例與懶漢式單例

單例模式&#xff08;Singleton Pattern&#xff09;詳解一、單例模式簡介 單例模式&#xff08;Singleton Pattern&#xff09; 是一種 創建型設計模式&#xff0c;它確保一個類只有一個實例&#xff0c;并提供一個全局訪問點來獲取這個實例。&#xff08;對象創建型模式&…

vue3 el-table 行數據沾滿格自動換行

在使用 Vue 3 結合 Element Plus 的 <el-table> 組件時&#xff0c;如果你希望當表格中的行數據文本過長時能夠自動換行&#xff0c;而不是溢出到其他單元格或簡單地截斷&#xff0c;你可以通過以下幾種方式來實現&#xff1a;方法 1&#xff1a;使用 CSS最簡單的方法是通…

windows電腦遠程win系統服務器上的wsl2

情況 我自己使用win11筆記本電腦&#xff0c;想要遠程win11服務器上的wsl2 我這里只有服務器安裝了wsl2&#xff0c;win11筆記本沒有安裝 因此下面提到的Ubuntu終端指的是win服務器上的wsl2終端 一定要區分是在哪里輸入命令&#xff01;&#xff01; 安裝SSH 在服務器上&#x…

神經輻射場 (NeRF):重構三維世界的AI新視角

神經輻射場 (NeRF)&#xff1a;重構三維世界的AI新視角 舊金山蜿蜒起伏的街道上&#xff0c;一輛裝備12個攝像頭的Waymo自動駕駛測試車緩緩駛過。它記錄的280萬張街景圖像并未被簡單地拼接成平面地圖&#xff0c;而是被輸入一個名為Block-NeRF的神經網絡。數周后&#xff0c;一…

Kubernetes自動擴縮容方案對比與實踐指南

Kubernetes自動擴縮容方案對比與實踐指南 隨著微服務架構和容器化的廣泛采用&#xff0c;Kubernetes 自動擴縮容&#xff08;Autoscaling&#xff09;成為保障生產環境性能穩定與資源高效利用的關鍵技術。面對水平 Pod 擴縮容、垂直資源調整、集群節點擴縮容以及事件驅動擴縮容…

【CVPR2025】計算機視覺|SIREN: 元學習賦能!突破INR高分辨率圖像分類難題

論文地址&#xff1a;https://arxiv.org/pdf/2503.18123v1 代碼地址&#xff1a;https://github.com/SanderGielisse/MWT 關注UP CV縫合怪&#xff0c;分享最計算機視覺新即插即用模塊&#xff0c;并提供配套的論文資料與代碼。 https://space.bilibili.com/473764881 摘要 …

牛客周賽 Round 99

賽時成績如下&#xff1a;A. Round 99題目描述 對于給定的五位整數&#xff0c;檢查其中是否含有數字 99&#xff1b;換句話說&#xff0c;檢查是否存在相鄰的兩個數位&#xff0c;其值均為 。解題思路&#xff1a; 檢查相鄰的兩個數字是否均為9#include <bits/stdc.h> u…

從0到1搭建個人技術博客:用GitHub Pages+Hexo實現

一、為什么要搭建個人技術博客&#xff1f; 在技術圈&#xff0c;擁有個人博客的好處不言而喻&#xff1a; 簡歷加分項&#xff1a;面試官更青睞有技術沉淀的候選人知識系統化&#xff1a;輸出倒逼輸入&#xff0c;加深技術理解人脈拓展&#xff1a;吸引同行關注&#xff0c;…

Ubuntu22.04 設置顯示存在雙屏卻無法雙屏顯示

文章目錄一、背景描述二、解決方法一、背景描述 回到工位后&#xff0c;發現昨天離開時還可正常顯示的雙屏&#xff0c;今早ubuntu22.04 的設置界面顯示有雙屏&#xff0c;但外接的顯示屏無法正常顯示。 首先&#xff0c;查看當前圖像處理顯卡是否為N卡&#xff0c;沒錯&#…

高亞科技簽約奕源金屬,助力打造高效智能化采購管理體系

深圳市奕源金屬制品有限公司近日&#xff0c;國內企業管理軟件服務商高亞科技與深圳市奕源金屬制品有限公司&#xff08;以下簡稱“奕源金屬”&#xff09;正式簽約&#xff0c;雙方將基于高亞科技自主研發的8Manage SRM采購管理系統&#xff0c;共同推動奕源金屬采購管理的數字…

數據結構之map

map的基本介紹我們常常把map稱之為映射&#xff0c;就是將一個元素&#xff08;通常稱之為key鍵&#xff09;與一個相對應的值&#xff08;通常稱之為value&#xff09;關聯起來&#xff0c;比如說一個學生的名字&#xff08;key&#xff09;有與之對應的成績&#xff08;value…

vue3 canvas 選擇器 Canvas 增加頁面性能

文章目錄Vue3 選擇器 Canvas 增加頁面性能基于Vue3 Composition API和Canvas實現的交互式選擇器&#xff0c;支持PC端和移動端的拖動選擇、多選取消選擇功能vue3組件封裝html代碼Vue3 選擇器 Canvas 增加頁面性能 基于Vue3 Composition API和Canvas實現的交互式選擇器&#xf…

Python 實戰:打造多文件批量重命名工具

引言在實際運維、測試、數據分析、開發流程中&#xff0c;我們經常會處理成百上千條命令操作&#xff0c;例如&#xff1a;各種腳本任務&#xff08;啟動、備份、重啟、日志查看&#xff09;數據處理流程&#xff08;爬取 → 清洗 → 統計 → 可視化&#xff09;配置自動化&…

設計模式筆記_結構型_代理模式

1. 代理模式介紹代理模式是一種結構型設計模式&#xff0c;它允許你提供一個代理對象來控制對另一個對象的訪問。代理對象通常在客戶端和目標對象之間起到中介作用&#xff0c;能夠在不改變目標對象的前提下增加額外的功能操作&#xff0c;比如延遲初始化、訪問控制、日志記錄等…

C語言<數據結構-單鏈表>(收尾)

上篇博客我將基礎的尾插、尾刪、頭插、頭刪逐一講解了&#xff0c;這篇博客將對上篇博客進行收尾&#xff0c;講一下指定位置操作增刪以及查找這幾個函數&#xff0c;其實大同小異&#xff1a;一.查找函數&#xff1a;查找函數其實就是一個簡單的循環遍歷&#xff0c;所以不加以…

十年架構心路:從單機到云原生的分布式系統演進史

十年架構心路&#xff1a;從單機到云原生的分布式系統演進史 這里寫目錄標題十年架構心路&#xff1a;從單機到云原生的分布式系統演進史一、技術生涯的起點&#xff1a;單體架構的黃金時代1.1 典型技術棧1.2 記憶深刻的故障二、分布式架構轉型期2.1 服務化拆分實踐2.2 分布式事…

使用docker搭建nginx

安裝docker 和 docker compose驗證docker版本配置docker目錄配置代理&#xff0c;使docker能訪問外網能否ping通最后直接拉入鏡像即可docker pull nginx

Intel新CPU助攻:微軟Copilot+將登陸臺式電腦

微軟的Copilot PC計劃已經推出一年多&#xff0c;但目前僅支持平板電腦和筆記本電腦&#xff0c;以及少數迷你電腦。 隨著Intel下一代桌面處理器——代號為“Arrow Lake Refresh”的推出&#xff0c;Copilot PC功能有望擴展到桌面計算機。 要支持Copilot PC的所有功能&#xff…