SpringCloud 微服務全棧體系(十六)

第十一章 分布式搜索引擎 elasticsearch

六、DSL 查詢文檔

  • elasticsearch 的查詢依然是基于 JSON 風格的 DSL 來實現的。

1. DSL 查詢分類

  • Elasticsearch 提供了基于 JSON 的 DSL(Domain Specific Language)來定義查詢。常見的查詢類型包括:

    • 查詢所有:查詢出所有數據,一般測試用。例如:match_all

    • 全文檢索(full text)查詢:利用分詞器對用戶輸入內容分詞,然后去倒排索引庫中匹配。例如:

      • match_query
      • multi_match_query
    • 精確查詢:根據精確詞條值查找數據,一般是查找 keyword、數值、日期、boolean 等類型字段。例如:

      • ids
      • range
      • term
    • 地理(geo)查詢:根據經緯度查詢。例如:

      • geo_distance
      • geo_bounding_box
    • 復合(compound)查詢:復合查詢可以將上述各種查詢條件組合起來,合并查詢條件。例如:

      • bool
      • function_score
  • 查詢的語法基本一致:

GET /indexName/_search
{"query": {"查詢類型": {"查詢條件": "條件值"}}
}
  • 以查詢所有為例,其中:

    • 查詢類型為 match_all
    • 沒有查詢條件
// 查詢所有
GET /indexName/_search
{"query": {"match_all": {}}
}
  • 其它查詢無非就是查詢類型查詢條件的變化。

2. 全文檢索查詢

2.1 使用場景
  • 全文檢索查詢的基本流程如下:

    • 對用戶搜索的內容做分詞,得到詞條
    • 根據詞條去倒排索引庫中匹配,得到文檔 id
    • 根據文檔 id 找到文檔,返回給用戶
  • 比較常用的場景包括:

    • 商城的輸入框搜索
    • 百度輸入框搜索
  • 例如京東:

在這里插入圖片描述

  • 因為是拿著詞條去匹配,因此參與搜索的字段也必須是可分詞的 text 類型的字段。
2.2 基本語法
  • 常見的全文檢索查詢包括:

    • match 查詢:單字段查詢
    • multi_match 查詢:多字段查詢,任意一個字段符合條件就算符合查詢條件
  • match 查詢語法如下:

GET /indexName/_search
{"query": {"match": {"FIELD": "TEXT"}}
}
  • mulit_match 語法如下:
GET /indexName/_search
{"query": {"multi_match": {"query": "TEXT","fields": ["FIELD1", " FIELD12"]}}
}
2.3 示例
  • match 查詢示例:

在這里插入圖片描述

  • multi_match 查詢和 match 查詢結果是一樣的。

  • 因為我們將 brand、name、business 值都利用 copy_to 復制到了 all 字段中。因此你根據三個字段搜索,和根據 all 字段搜索效果當然一樣了。

  • 但是,搜索字段越多,對查詢性能影響越大,因此建議采用 copy_to,然后單字段查詢的方式。

2.4.總結
  • match 和 multi_match 的區別是什么?

    • match:根據一個字段查詢
    • multi_match:根據多個字段查詢,參與查詢字段越多,查詢性能越差

3. 精準查詢

  • 精確查詢一般是查找 keyword、數值、日期、boolean 等類型字段。所以不會對搜索條件分詞。常見的有:

    • term:根據詞條精確值查詢
    • range:根據值的范圍查詢
3.1 term 查詢
  • 因為精確查詢的字段是搜不分詞的字段,因此查詢的條件也必須是不分詞的詞條。查詢時,用戶輸入的內容跟自動值完全匹配時才認為符合條件。如果用戶輸入的內容過多,反而搜索不到數據。

  • 語法說明:

// term查詢
GET /indexName/_search
{"query": {"term": {"FIELD": {"value": "VALUE"}}}
}
3.2 range 查詢
  • 范圍查詢,一般應用在對數值類型做范圍過濾的時候。比如做價格范圍過濾。

  • 基本語法:

// range查詢
GET /indexName/_search
{"query": {"range": {"FIELD": {"gte": 10, // 這里的gte代表大于等于,gt則代表大于"lte": 20 // lte代表小于等于,lt則代表小于}}}
}
  • 示例:

在這里插入圖片描述

3.3 總結
  • 精確查詢常見的有哪些?

    • term 查詢:根據詞條精確匹配,一般搜索 keyword 類型、數值類型、布爾類型、日期類型字段
    • range 查詢:根據數值范圍查詢,可以是數值、日期的范圍

4. 地理坐標查詢

  • 所謂的地理坐標查詢,其實就是根據經緯度查詢,官方文檔:https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-queries.html

  • 常見的使用場景包括:

    • 攜程:搜索我附近的酒店
    • 滴滴:搜索我附近的出租車
    • 微信:搜索我附近的人
4.1 矩形范圍查詢
  • 矩形范圍查詢,也就是 geo_bounding_box 查詢,查詢坐標落在某個矩形范圍的所有文檔

  • 查詢時,需要指定矩形的左上右下兩個點的坐標,然后畫出一個矩形,落在該矩形內的都是符合條件的點。

  • 語法如下:

// geo_bounding_box查詢
GET /indexName/_search
{"query": {"geo_bounding_box": {"FIELD": {"top_left": { // 左上點"lat": 31.1,"lon": 121.5},"bottom_right": { // 右下點"lat": 30.9,"lon": 121.7}}}}
}
4.2 附近查詢
  • 附近查詢,也叫做距離查詢(geo_distance):查詢到指定中心點小于某個距離值的所有文檔。

  • 換句話來說,在地圖上找一個點作為圓心,以指定距離為半徑,畫一個圓,落在圓內的坐標都算符合條件

  • 語法說明:

// geo_distance 查詢
GET /indexName/_search
{"query": {"geo_distance": {"distance": "15km", // 半徑"FIELD": "31.21,121.5" // 圓心}}
}

5. 復合查詢

  • 復合(compound)查詢:復合查詢可以將其它簡單查詢組合起來,實現更復雜的搜索邏輯。常見的有兩種:

    • fuction score:算分函數查詢,可以控制文檔相關性算分,控制文檔排名
    • bool query:布爾查詢,利用邏輯關系組合多個其它的查詢,實現復雜搜索
5.1 相關性算分
  • 當我們利用 match 查詢時,文檔結果會根據與搜索詞條的關聯度打分(_score),返回結果時按照分值降序排列。

  • 例如,我們搜索 “虹橋如家”,結果如下:

[{"_score" : 17.850193,"_source" : {"name" : "虹橋如家酒店真不錯",}},{"_score" : 12.259849,"_source" : {"name" : "外灘如家酒店真不錯",}},{"_score" : 11.91091,"_source" : {"name" : "迪士尼如家酒店真不錯",}}
]
  • 在 elasticsearch 中,早期使用的打分算法是 TF-IDF 算法,公式如下:

在這里插入圖片描述

  • 在后來的 5.1 版本升級中,elasticsearch 將算法改進為 BM25 算法,公式如下:

在這里插入圖片描述

  • TF-IDF 算法有一個缺陷,就是詞條頻率越高,文檔得分也會越高,單個詞條對文檔影響較大。而 BM25 則會讓單個詞條的算分有一個上限,曲線更加平滑:

在這里插入圖片描述

  • 小結:elasticsearch 會根據詞條和文檔的相關度做打分,算法由兩種:

    • TF-IDF 算法
    • BM25 算法,elasticsearch5.1 版本后采用的算法
5.2 算分函數查詢
  • 根據相關度打分是比較合理的需求,但合理的不一定是產品經理需要的。

  • 以百度為例,你搜索的結果中,并不是相關度越高排名越靠前,而是誰掏的錢多排名就越靠前。如圖:

在這里插入圖片描述

  • 要想人為控制相關性算分,就需要利用 elasticsearch 中的 function score 查詢了。
5.2.1 語法說明

在這里插入圖片描述

  • function score 查詢中包含四部分內容:

    • 原始查詢條件:query 部分,基于這個條件搜索文檔,并且基于 BM25 算法給文檔打分,原始算分(query score)
    • 過濾條件:filter 部分,符合該條件的文檔才會重新算分
    • 算分函數:符合 filter 條件的文檔要根據這個函數做運算,得到的函數算分(function score),有四種函數
      • weight:函數結果是常量
      • field_value_factor:以文檔中的某個字段值作為函數結果
      • random_score:以隨機數作為函數結果
      • script_score:自定義算分函數算法
    • 運算模式:算分函數的結果、原始查詢的相關性算分,兩者之間的運算方式,包括:
      • multiply:相乘
      • replace:用 function score 替換 query score
      • 其它,例如:sum、avg、max、min
  • function score 的運行流程如下:

    • 根據原始條件查詢搜索文檔,并且計算相關性算分,稱為原始算分(query score)
    • 根據過濾條件,過濾文檔
    • 符合過濾條件的文檔,基于算分函數運算,得到函數算分(function score)
    • 原始算分(query score)和函數算分(function score)基于運算模式做運算,得到最終結果,作為相關性算分。
  • 因此,其中的關鍵點是:

    • 過濾條件:決定哪些文檔的算分被修改
    • 算分函數:決定函數算分的算法
    • 運算模式:決定最終算分結果
5.2.2 示例
  • 需求:給“如家”這個品牌的酒店排名靠前一些

  • 翻譯一下這個需求,轉換為之前說的四個要點:

    • 原始條件:不確定,可以任意變化
    • 過濾條件:brand = “如家”
    • 算分函數:可以簡單粗暴,直接給固定的算分結果,weight
    • 運算模式:比如求和
  • 因此最終的 DSL 語句如下:

GET /hotel/_search
{"query": {"function_score": {"query": {  .... }, // 原始查詢,可以是任意條件"functions": [ // 算分函數{"filter": { // 滿足的條件,品牌必須是如家"term": {"brand": "如家"}},"weight": 2 // 算分權重為2}],"boost_mode": "sum" // 加權模式,求和}}
}
  • 測試,在未添加算分函數時,如家得分如下:

在這里插入圖片描述

  • 添加了算分函數后,如家得分就提升了:

在這里插入圖片描述

5.2.3 小結
  • function score query 定義的三要素是什么?

    • 過濾條件:哪些文檔要加分
    • 算分函數:如何計算 function score
    • 加權方式:function score 與 query score 如何運算
5.3 布爾查詢
  • 布爾查詢是一個或多個查詢子句的組合,每一個子句就是一個子查詢。子查詢的組合方式有:

    • must:必須匹配每個子查詢,類似“與”
    • should:選擇性匹配子查詢,類似“或”
    • must_not:必須不匹配,不參與算分,類似“非”
    • filter:必須匹配,不參與算分
  • 比如在搜索酒店時,除了關鍵字搜索外,我們還可能根據品牌、價格、城市等字段做過濾。

請添加圖片描述

  • 每一個不同的字段,其查詢的條件、方式都不一樣,必須是多個不同的查詢,而要組合這些查詢,就必須用 bool 查詢了。

  • 需要注意的是,搜索時,參與打分的字段越多,查詢的性能也越差。因此這種多條件查詢時,建議這樣做:

    • 搜索框的關鍵字搜索,是全文檢索查詢,使用 must 查詢,參與算分
    • 其它過濾條件,采用 filter 查詢。不參與算分
5.3.1 語法示例
GET /hotel/_search
{"query": {"bool": {"must": [{"term": {"city": "上海" }}],"should": [{"term": {"brand": "皇冠假日" }},{"term": {"brand": "華美達" }}],"must_not": [{ "range": { "price": { "lte": 500 } }}],"filter": [{ "range": {"score": { "gte": 45 } }}]}}
}
5.3.2 示例
  • 需求:搜索名字包含“如家”,價格不高于 400,在坐標 31.21,121.5 周圍 10km 范圍內的酒店。

  • 分析:

    • 名稱搜索,屬于全文檢索查詢,應該參與算分。放到 must 中
    • 價格不高于 400,用 range 查詢,屬于過濾條件,不參與算分。放到 must_not 中
    • 周圍 10km 范圍內,用 geo_distance 查詢,屬于過濾條件,不參與算分。放到 filter 中

在這里插入圖片描述

5.3.3 小結
  • bool 查詢有幾種邏輯關系?

    • must:必須匹配的條件,可以理解為“與”
    • should:選擇性匹配的條件,可以理解為“或”
    • must_not:必須不匹配的條件,不參與打分
    • filter:必須匹配的條件,不參與打分

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

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

相關文章

P1030 [NOIP2001 普及組] 求先序排列

1.先找根(后序最后一個元素) 2.以根分中序為兩個中序即: (相當于分為兩個子樹) A中序 對應->A后序 (長度對應) B中序 對應->B后序 (長度對應) 遞歸循壞即可(中序長度小…

【數據結構(C語言)】淺談棧和隊列

目錄 文章目錄 前言 一、棧 1.1 棧的概念及結構 1.2 棧的實現 1.2.1. 支持動態增長的棧的結構 1.2.2 初始化棧 1.2.3 入棧 1.2.4 出棧 1.2.5 獲取棧頂元素 1.2.6 獲取棧中有效元素個數 1.2.7 檢查棧是否為空 1.2.8 銷毀棧 二、隊列 2.1 隊列的概念及結構 2.2 隊…

Javaweb之前后臺分離開發介紹的詳細解析

2.1 前后臺分離開發介紹 在之前的課程中,我們介紹過,前端開發有2種方式:前后臺混合開發和前后臺分離開發。 前后臺混合開發,顧名思義就是前臺后臺代碼混在一起開發,如下圖所示: 這種開發模式有如下缺點&a…

守護進程的理解

什么是守護進程 daemon False # 是否以守護進程方式運行,True守護,False 非守護 在這段代碼中,daemon 變量的值決定了進程是否以守護進程方式運行。如果 daemon 的值為 True,則表示進程將以守護進程方式運行,否則為…

使用vcpkg安裝庫失敗的解決方法

1、前言 vcpk是是一款開源的c/c庫管理工具,尤其是在windows平臺,可以幫助我們很好的管理各種依賴包。 在windows環境做c/c開發的人應該都深有體會,有時候編譯需要下載一堆依賴庫,導致搭建編譯環境特別麻煩。但是,通過v…

前端 vue 面試題(二)

文章目錄 如何讓vue頁面重新渲染組件間通信vue為什么要mutation、 action操作插槽、具名插槽、作用域插槽vue編譯使用的是什么庫?vue怎么實現treeshakingwebpack實現treeshaking為什么只有es module 能支持 tree shaking mixin 的作用mixin的底層原理nexTick原理vue…

預處理機制

跟著肯哥(不是我)學預處理機制 預處理類別 宏定義:#define 將文本替換為表達式或語句 條件編譯:#ifdef、#ifndef和#if、#elif、#endif 根據標識符是否被定義選擇編譯代碼 頭文件包含:#include 將其他文件&#x…

Jmeter怎么實現接口關聯?

用于接口測試時,后一個接口經常需要用到前一次接口返回的結果,應該如何獲取前一次請求的結果值,應用于后一個接口呢,拿一個登錄的例子來說明如何獲取。 1、打開jmeter,新建一個測試計劃,在測試計劃里新建一…

將所有圖片居中對齊

Ctrl h 調出替換框 ^g表示所有圖片 格式里面選擇段落 全部替換

winlogbeat采集windows日志

下載鏈接 https://www.elastic.co/cn/downloads/past-releases/winlogbeat-7-16-2 配置文件 # ---------------------------- Elasticsearch Output ---------------------------- output.elasticsearch:# Array of hosts to connect to.hosts: ["192.168.227.160:9200&…

Vue3中如何響應式解構 props

目錄 1,前言2,解決2.1,利用插件,實現編譯時轉換2.2,toRef 和 toRefs 1,前言 Vue3 中為了保持響應性,始終需要以 props.x 的方式訪問這些 prop。這意味著不能夠解構 defineProps 的返回值&#…

Navicat 技術指引 | 適用于 GaussDB 的數據遷移工具

Navicat Premium(16.2.8 Windows版或以上) 已支持對 GaussDB 主備版的管理和開發功能。它不僅具備輕松、便捷的可視化數據查看和編輯功能,還提供強大的高階功能(如模型、結構同步、協同合作、數據遷移等),這…

Cesium 展示——地球以及渲染數據導出(下載)為圖片或 pdf

文章目錄 需求分析新加需求分析第一種方式第二種方式需求 將 Cesium 球體以及渲染數據導出為 jpg/png/pdf 分析 獲取場景 scene 信息,轉為image 的 octet-stream 流 進行下載為圖片 /*** @todo canvas 導出圖片* @param {string} dataurl - 地址* @return {Blob}*/ functio…

Failed to resolve import “@/..“ from “src/...“ @找不到路徑

安裝path npm install --save-dev types/node再修改 vite.config.ts 中的配置即可 import { defineConfig } from "vite" import react from "vitejs/plugin-react"import path from "path" // 需安裝此模塊// https://vitejs.dev/config/ expo…

設備健康管理平臺助力鋰電企業實現可持續發展

隨著鋰電池產業的快速發展,設備的穩定運行和精準維護對于鋰電企業來說至關重要。傳統的設備維護方式在效率和全面性方面存在局限,無法滿足鋰電行業對設備管理的需求。然而,通過設備健康管理平臺的引入,鋰電企業現在可以充分發揮其…

XSLVGL2.0 User Manual 頁面管理器(v2.0)

XSLVGL2.0 開發手冊 XSLVGL2.0 User Manual 頁面管理器 1、概述2、特性3、APIs3.1、xs_page_init3.2、xs_page_wait_inited3.3、xs_page_exit3.4、xs_page_acquire3.5、xs_page_release3.6、xs_page_set_bootlogo3.7、xs_page_setup_clear_finish3.8、xs_page_setup_is_finish…

【LeetCode:1410. HTML 實體解析器 | 模擬+哈希表+字符串+庫函數】

🚀 算法題 🚀 🌲 算法刷題專欄 | 面試必備算法 | 面試高頻算法 🍀 🌲 越難的東西,越要努力堅持,因為它具有很高的價值,算法就是這樣? 🌲 作者簡介:碩風和煒,…

【C語言】中,輸入一個數組,實現將輸入的n個數字按照從大到小的順序輸出。【通俗簡單易懂】

本篇文章中,我們將講述在C語言中,輸入一個數組,如何用for循環實現將輸入的n個數字按照從大到小輸出。 一.定義數組并初始化 首先,我們定義一個整形的數組并將其初始化。輸入n,來決定數組中整數的個數。 然后用for循…

通過HTML網頁對mysql數據庫進行增刪改查(CRUD實例)

首先我們得了解一下大致的架構 ,如下: 我們采用自底向上的方式進行開發, 一、先寫mysql數據庫 二、再寫java后端(Spring MVC架構)(這個是什么東西不懂不要緊,跟著步驟做就行了) 三、最后寫前端頁面(HTML) 一、 Mysql數據庫部分 我們要通過網頁對數據庫進行開發,…

解決:Gitee + PicGo配置圖床失敗

解決:Gitee PicGo配置圖床失敗 PicGo安裝插件的時候選擇:gitee-uploader,不要選擇gitee! 在Gitee新建的圖床倉庫中設置一個images文件夾,用來保存上傳的圖片,但是要注意在PicGo中的path中要寫上路徑/img…