Elasticsearch Query DSL 整理總結(二)—— 要搞懂 Match Query,看這篇就夠了

来源:https://www.cnblogs.com/reycg-blog/archive/2018/11/23/10002794.html
-Advertisement-
Play Games

昨天是感恩節,上幼兒園的女兒在老師的叮囑下,晚上為我和老婆洗了腳(形式上的^_^),還給我們每人端了一杯水。看著孩子一天天的長大,懂事,感覺很開心。話說咱們程式員這麼辛苦是為了什麼?不就是為了老婆,孩子,熱炕頭,有一個溫暖幸福的家庭,再捎帶著用代碼改變一下世界嗎?想到這裡,頓時覺得學習,創作博客的勁... ...


目錄

引言

昨天是感恩節,上幼兒園的女兒在老師的叮囑下,晚上為我和老婆洗了腳(形式上的^_^),還給我們每人端了一杯水。看著孩子一天天的長大,懂事,感覺很開心,話說咱們程式員這麼辛苦是為了什麼?不就是為了老婆,孩子,熱炕頭,有一個溫暖幸福的家庭,再捎帶著用代碼改變一下世界嗎?想到這裡,頓時覺得學習,創作博客的勁頭也的更足了。哈哈,扯遠了,書歸正傳,今天我們來聊聊 Match Query。

Match Query 是最常用的 Full Text Query 。無論需要查詢什麼欄位, match 查詢都應該會是首選的查詢方式。它既能處理全文欄位,又能處理精確欄位。

構建示例

為了能夠在後面能深入理解 Match Query 中的各個屬性的意義,我們先構建一個 index 示例(有興趣的同學只要將下麵欄位粘貼到 sense 中就可以創建)。

PUT matchtest
{ 
}

PUT matchtest/_mapping/people
{
  "properties": {
    "age": {
      "type": "integer"
    },
    "hobbies": {
      "type": "text"
    },
    "name": {
      "type": "keyword"
    }
  }
}

PUT matchtest/people/1
{
  "name" : "Jim",
  "age": 10,
  "hobbies": "football, basketball, pingpang"
}


PUT matchtest/people/2
{
  "name" : "Tom",
  "age": 12,
  "hobbies": "swimming, football"
}

match

operator 參數

match 查詢是一種 bool 類型的查詢。什麼意思呢?舉個例子,查詢 people type 的 hobbies 為 football basketball

GET matchtest/people/_search
{
  "query": {
    "match": {
      "hobbies": "football basketball"
    }
  }
}

會將上面的兩個文檔都搜索出來。為什麼?上面的查詢其實隱藏了一個預設參數operator , 它的預設值是 or ,也就是說上面的查詢也可以寫成這種形式

GET matchtest/people/_search
{
  "query": {
    "match": {
      "hobbies": {
        "query": "football basketball",
        "operator": "or"
      }
    }
  }
}

這樣就比較容易理解了,既然是 or 操作符,就表示只要查詢的文檔的 hobbies 欄位中含有 footballbasketball 任意一個,就可以被匹配到。

如果將 operator 操作符的值改為 and ,則表示需要同時包含 footballbasketball , 得到的結果就只能是 文檔 1 Jim 小朋友了。

analyzer

analyzer 屬性是指在對查詢文本分析時的分析器

  • 如果沒有指定則會使用欄位mapping 時指定的分析器
  • 如果欄位在 mapping 時也沒有明顯指定,則會使用預設的 search analyzer。

這裡我們也沒有指定,就會使用預設的,就不舉例了,在後面文章講解 analyzer 時再拓展。

lenient 參數

預設值是 false , 表示用來在查詢時如果數據類型不匹配且無法轉換時會報錯。如果設置成 true 會忽略錯誤。

例如, 例子中的 ageinteger 類型的,如果查詢 age=xxy ,就會導致無法轉換而報錯。

GET matchtest/_search
{
  "query": {
    "match": {
      "age" : {
        "query": "xxx"
      }
    }
  }
}

而如果將 lenient 參數設置為 true ,就會忽略這個錯誤

GET matchtest/_search
{
  "query": {
    "match": {
      "age" : {
        "query": "xxx",
        "lenient": true
      }
    }
  }
}

註意,如果將 age 欄位的值設置為字元串 "10", 來查詢,由於能夠轉換成整數,這時 elastic 內部會將 字元串先轉換成整數再做查詢,不會報錯。

Fuzziness

fuzzniess 參數

fuzziness 參數可以使查詢的欄位具有模糊搜索的特性。來先瞭解下什麼是模糊搜索。

什麼是模糊搜索?

模糊搜索是指系統允許被搜索信息和搜索提問之間存在一定的差異,這種差異就是“模糊”在搜索中的含義。例如,查找名字Smith時,就會找出與之相似的Smithe, Smythe, Smyth, Smitt等。

——百度百科

通過模糊搜索可以查詢出存在一定相似度的單詞,那麼怎麼計算兩個單詞是否有相似度以及相似度的大小呢?這就要瞭解下另外一個概念:Levenshtein Edit Distance

Levenshtein Edit Distance

Levenshtein Edit Distance 叫做萊文斯坦距離**,是編輯距離的一種。指兩個字串之間,由一個轉成另一個所需的最少編輯操作次數。允許的編輯操作包括將一個字元替換成另一個字元,插入一個字元,刪除一個字元。

例如,單詞 "god" 只需要插入一個 'o' 字元就可以變為 "good",因此它們之間的編輯距離為 1。

fuzziness 參數取值規則

瞭解了上面兩個概念,回過頭再來看下 fuzziness 參數。

在查詢 text 或者 keyword 類型的欄位時, fuzziness 可以看做是萊文斯坦距離。

fuzziness 參數的取值如下

  • 0,1,2 表示最大可允許的萊文斯坦距離

  • AUTO

    會根據詞項的長度來產生可編輯距離,它還有兩個可選參數,形式為AUTO:[low],[high], 分別表示短距離參數和長距離參數;如果沒有指定,預設值是 AUTO:3,6 表示的意義如下

    • 0..2

      單詞長度為 0 到 2 之間時必須要精確匹配,這其實很好理解,單詞長度太短是沒有相似度可言的,例如 'a' 和 'b'。

    • 3..5

      單詞長度 3 到 5 個字母時,最大編輯距離為 1

    • >5

      單詞長度大於 5 個字母時,最大編輯距離為 2

    最佳實踐: fuzziness 在絕大多數場合都應該設置成 AUTO

如果不設置 fuziness 參數,查詢是精確匹配的。

來看例子,上面創建了一個 doc

PUT matchtest/people/1
{
  "name" : "Jim",
  "age": 10,
  "hobbies": "football, basketball, pingpang"
}

設置 fuzzinessAUTO

  • 其中 hobbies 欄位的值 football 長度 > 5, 此時我們找一個編輯距離為 2 的單詞 footba22 來查詢,應該匹配到
  • 其中 name 欄位的值 jim 長度在 3 和 5 之間,此時找一個編輯距離為 1 的單詞 jiO 應匹配到,而編輯距離為 2 的 jOO 就不應匹配到。

來,驗證下

GET matchtest/_search
{
  "query": {
    "match": {
      "hobbies": {
        "query": "footba22",
        "fuzziness": "AUTO"
      }
    }
  }
}

GET matchtest/_search
{
  "query": {
    "match": {
      "name": {
        "query": "jiO",
        "fuzziness": "AUTO"
      }
    }
  }
}


GET matchtest/_search
{
  "query": {
    "match": {
      "name": {
        "query": "jOO",
        "fuzziness": "AUTO"
      }
    }
  }
}

prefix_length

prefix_length 表示不能沒模糊化的初始字元數。由於大部分的拼寫錯誤發生在詞的結尾,而不是詞的開始,使用 prefix_length 就可以完成優化。註意 prefix_length 必須結合 fuzziness 參數使用。

例如,在查詢 hobbies 中的 football 時,將 prefix_length 參數設置為 3,這時 foatball 將不能被匹配。

GET matchtest/_search
{
  "query": {
    "match": {
      "hobbies": {
        "query": "foatball",
        "fuzziness": "AUTO",
        "prefix_length": 3
      }
    }
  }
}

TODO(max_expansions 參數對於 match 查詢而言,沒理解表示的意義,如果您知道這個參數的用法,請給我留言告知,不勝感謝! )

Zero terms Query

先看例子, 先創建一個文檔 zero_terms_query_test 其中 message 欄位使用 stop 分析器,這個分析器會將 stop words 停用詞在索引時全都去掉。

PUT matchtest1

PUT matchtest1/_mapping/zero_terms_query_test
{
  "properties": {
    "message": {
      "type": "text",
      "analyzer": "stop"
    }
  }
}


PUT matchtest1/zero_terms_query_test/1
{
  "message": "to be or not to be"
}

GET matchtest1/_search
{
  "query": {
    "match": {
      "message": {
        "query": "to be or not to be",
        "operator": "and",
        "zero_terms_query": "none"
      }
    }
  }
}

那麼就像 message 欄位中的 to be or not to be 這個短語中全部都是停止詞,一過濾,就什麼也沒有了,得不到任何 tokens, 那搜索時豈不什麼都搜不到。

POST _analyze
{
  "analyzer": "stop",
  "text": "to be or not to be"
}

zero_terms_query 就是為瞭解決這個問題而生的。它的預設值是 none ,就是搜不到停止詞(對 stop 分析器欄位而言),如果設置成 all ,它的效果就和 match_all 類似,就可以搜到了。

GET matchtest1/_search
{
  "query": {
    "match": {
      "message": {
        "query": "to be or not to be",
        "operator": "and",
        "zero_terms_query": "all"
      }
    }
  }
}

Cutoff frequency

查詢字元串時的詞項會分成低頻詞(更重要)和高頻詞(次重要)兩類,像前面所說的停用詞 (stop word)就屬於高頻詞,它雖然出現頻率較高,但在匹配時可能並不太相關。實際上,我們往往是想要文檔能儘可能的匹配那些低頻詞,也就是更重要的詞項

要實現這個需求,只要在查詢時配置 cutoff_frequency 參數就可以了。假設我們將 cutoff_frequency 設置成 0.01 就表示

  • 任何詞項在文檔中超過 1%, 被認為是高頻詞
  • 其他的詞項會被認為低頻詞

從而將高頻詞(次重要的詞)挪到可選子查詢中,讓它們只參與評分,而不參與匹配;高頻詞(更重要的詞)參與匹配和評分。

這樣一來,就不再需要 stopwords 停用詞文件了,從而變成了動態生成停用詞: 高頻詞就會被看做是停用詞。這種配置只是對於詞項比較多的場合如 email body,文章等適用,文字太少, cutoff_frequency 選項設置的意義就不大了。

cutoff_frequency 配置有兩種形式

  • 指定為一個分數( 0.01 )表示出現頻率
  • 指定為一個正整數( 5 )則表示出現次數

下麵給個例子, 在創建的 3 個文檔中都包含 "be " 的單詞,在查詢時將 cutoff_frequency 參數設置為 2, 表示 "be" 就是高頻詞,只會參與評分,但在匹配時不做考慮。

此時查詢的內容為 "to be key" ,由於 "be" 詞項是高頻詞,因為在文檔中必須要存在 "to" 或者 "key" 才能匹配,因此文檔 3 不能匹配。

PUT /matchtest2

PUT matchtest2/_mapping/cutoff_frequency_test
{
  "properties": {
    "message": {
      "type": "text"
    }
  }
}

PUT matchtest2/cutoff_frequency_test/1
{
  "message": "to be or not to be to be or"
}

PUT matchtest2/cutoff_frequency_test/2
{
  "message": "be key or abc"
}

PUT matchtest2/cutoff_frequency_test/3
{
  "message": "or to be or to to be or"
}

GET matchtest2/_search
{
  "query": {
    "match": {
      "message": {
        "query": "to be key",
        "cutoff_frequency": 2
      }
    }
  }
}

synonyms

synonyms 是指同義詞,只要索引和欄位中配置了同義詞過濾器,match 查詢是支持多詞條的同義詞擴展的。在應用過濾器後,解析器會對每個多次條同義詞創建一個語句查詢。

例如,同義詞 USA, united states of America 就會構建出 (USA OR ("united states of America"))。看下麵例子:

PUT /matchtest4
{
    "settings": {
        "index" : {
            "analysis" : {
                "analyzer" : {
                    "synonym" : {
                        "tokenizer" : "whitespace",
                        "filter" : ["synonym"]
                    }
                },
                "filter" : {
                    "synonym" : {
                        "type" : "synonym",
                        "synonyms" : [
                            "USA, united states of America"
                        ]
                    }
                }
            }
        }
    }
}

PUT /matchtest4/_mapping/synonyms_test
{
  "properties": {
    "message": {
      "type": "text",
      "analyzer": "synonym"
    }
  }
}

PUT /matchtest4/synonyms_test/1
{
  "message": "united states of America people"
}


GET /matchtest4/_search
{
  "query": {
    "match": {
      "message": {
        "query": "USA"
      }
    }
  }
}

小結

本文以代碼實例的方式完整的講解了 Match Query 的各種使用場景和參數意義。下篇會講解 Match Phrase Query 敬請期待。

參考文檔

系列文章列表

Query DSL

  1. Query DSL 概要,MatchAllQuery,全文查詢簡述

Java Rest Client API

  1. Elasticsearch Java Rest Client API 整理總結 (一)——Document API
  2. Elasticsearch Java Rest Client API 整理總結 (二) —— SearchAPI
  3. Elasticsearch Java Rest Client API 整理總結 (三)——Building Queries

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Vue雙向榜單的原理 大家都知道Vue採用的是MVVM的設計模式,採用數據驅動實現雙向綁定,不明白雙向綁定原理的需要先補充雙向綁定的知識,在watch的處理中將運用到Vue的雙向榜單原理,所以再次回顧一下: Vue的數據通過Object.defineProperty設置對象的get和set實現對象屬 ...
  • DOM的全稱是Document Object Model 文檔對象模型,DOM定義了表示和修改文檔所需的對象、這些對象的行為和屬性以及這些對象之間的關係。 DOM對象即為宿主對象,由瀏覽器廠商定義,用來操作html的css功能的一類對象和集合。不過瀏覽器廠商之間大部分都遵循w3c標準。 簡單來說,D... ...
  • 創建型設計模式是設計模式的入門基礎,主要包括工廠方法模式、抽象工廠模式、建造者模式、原型模式、單例模式,以及簡單工廠模式,本文對他們進行了分析對比,總結了創建型模式之間的區別聯繫 ...
  • 一、概念 工廠方法模式:用來封裝對象的創建。工廠方法模式(Factory Method Pattern)通過讓 子類 決定該創建的對象是什麼,來達到將對象創建的過程封裝的目的。這樣,關於超類的代碼和子類創建對象的代碼之間就解耦了。 抽象工廠模式(Abstract Factory Pattern):提 ...
  • 直接使用 JDBC 的場景,如果代碼中存在拼接 SQL 語句,那麼很有可能會產生註入,如 安全的寫法是使用 參數化查詢 ( parameterized queries ),即 SQL 語句中使用參數綁定( ? 占位符 ) 和 PreparedStatement,如 使用PreparedStateme ...
  • 1.Map 遍歷: 2.map的長度: int size=Map.size(); ...
  • 前言 網際網路聯繫的是世界各地的電腦(通過電纜),萬維網聯繫的是網上的各種各樣資源(通過文本超鏈接),如靜態的HTML文件,動態的軟體程式······。由於萬維網的存在,處於網際網路中的每台電腦可以很方便地進行消息交流、文件資源交流······。基於網際網路的幫助,我們可以在web客戶端(如瀏覽器等) ...
  • FileManager 圖片管理插件是 TinyMCE下 免費且非官方的文件插件,可上傳/管理的類型包括:文件,圖片,視頻。 本教程主要展示大叔在為安裝開發插件過程中進行調整的修改記錄。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...