Term-level Queries
參考:https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-exists-query
一、Term Query
Term Query 是 term 精準查詢。需要注意的是,在進行 Term Query 的時候,要避免 text 類型的字段,因為 Elasticsearch 構建倒排索引時會改變 text 字段的值,即它會進行分詞,這會導致我們在精準匹配 text 字段值時會比較困難。
如果想要查詢 text 類型的值,需要使用 match query
1.1、term 查詢的相關參數介紹
{"query" : {"term": {"field": {"value": "xxx","boost": 1.0}}}
}
- field: 即我們想要查詢的字段
- value: 即我們想要查詢的單詞,只有在 term 完全匹配字段值(包含大小寫和空格)時,才會返回文檔。ps: 這里我實驗了一下,準確來說應該是精準匹配該字段在分詞的最小 term 。
- boost: 浮點類型,它用來對該查詢條件進行提權或降權,在多個查詢條件下,該字段對相關性算分的影響
- case_insensitive: 這個字段在 7.10.0 版本添加,控制該查詢字段是否考慮大小寫,true 的情況忽略大小寫,false 的情況考慮大小寫
1.2、RESTful API 示例
PUT my_index_00001
{"mappings": {"properties": {"full-text":{"type": "text"}}}
}PUT my_index_00001/_doc/1
{"full-text":"Quick Brown Foxes!"
}// 使用 term 查詢,會返回無結果,因為 term 查詢不會對文本進行分詞,而 text 類型的內容會被分詞
POST my_index_00001/_search
{"query": {"term": {"full-text": {"value": "Quick", // Quick Brown Foxes! 不會返回數據"boost": 1.0,"case_insensitive": true // 大小寫敏感控制, true 忽略大小寫、false 考慮大小寫}}}
}
二、Terms Query
在一次查詢中指定多個 Term 時,只要文檔匹配其中至少一個 Term,即可被檢索出來。
Terms Query 是在 Term Query 的基礎上,支持多值查詢。
2.1、terms 查詢的相關參數介紹
{"query": {"terms": {"field": [value1,value2,]"boost": 1.0}}
}
- field: 即我們想要查詢的字段
- value: 這里是一個數組
- 默認情況,es 限制這個數組的大小是 65536,我們也可以通過使用 setting 中的
index.max_terms_count
來改變這個限制。
- 默認情況,es 限制這個數組的大小是 65536,我們也可以通過使用 setting 中的
- boost: 浮點類型,它用來對該查詢條件進行提權或降權,在多個查詢條件下,該字段對相關性算分的影響
2.2、Terms Lookup 功能
我們也可以使用索引中已經存在的文檔的字段作為查詢的 Terms,來檢索其他符合條件的文檔,這個功能稱為 terms lookup。這個功能在查詢大量 Terms 時很有幫助。
2.2.1、相關參數介紹
- index: 指定索引
- id: 指定文檔 id
- path: 指定文檔字段,將該字段的值作為檢索的 terms value
2.3、RESTful API 示例
PUT my_index_00002
{"mappings": {"properties": {"color": {"type": "keyword"}}}
}PUT my_index_00002/_doc/1
{"color": ["blue","green","black"]
}PUT my_index_00002/_doc/2
{"color": ["blue"]
}// terms 示例
GET my_index_00002/_search
{"query": {"terms": {"color": ["blue","white"]}}
}// terms lookup 示例
GET my_index_00002/_search?pretty
{"query": {"terms": {"color": {"index": "my_index_00002","id": "2","path": "color"}}}
}
三、、Terms Set Query
Terms Set Query 是一種用于匹配文檔字段中多個值的至少一個或多個的高級查詢方式,適用于文檔中的字段是數組或集合的情況。它比普通的 terms 查詢更靈活,可以基于多個值的交集進行過濾。
我們在查詢過程中可以:
- 提供一個候選值集合
- Elasticsearch 會檢查文檔中指定字段的值,與這個集合的交集是否滿足某種最小匹配條件
- 這個”最小匹配條件“可以是一個固定數字,或者從文檔的另一個字段中動態獲取
3.1、RESTful API 示例
PUT job-candidates
{"mappings": {"properties": {"name":{"type": "keyword"},"programming_languages": {"type": "keyword"},"required_matches": {"type": "long"}}}
}// refresh 表示文檔創建后可以被立即檢索
PUT /job-candidates/_doc/1?refresh
{"name": "Jane Smith","programming_languages": [ "c++", "java" ],"required_matches": 2
}PUT /job-candidates/_doc/2?refresh
{"name": "Jason Response","programming_languages": [ "java", "php" ],"required_matches": 2
}GET /job-candidates/_search
{"query": {"terms_set": {"programming_languages": {"terms": [ "c++", "java", "php" ],"minimum_should_match_field": "required_matches" // 根據文檔的字段動態決定最小匹配數}}}
}GET /job-candidates/_search
{"query": {"terms_set": {"programming_languages": {"terms": [ "c++", "java", "php" ],"minimum_should_match": 2 // 固定值}}}
}GET /job-candidates/_search
{"query": {"terms_set": {"programming_languages": {"terms": ["c++","java","php"],"minimum_should_match_script": {// params.num_terms 就是傳入的 terms 的數量"source": "Math.min(params.num_terms, doc['required_matches'].value)" // 腳本動態指定}}}}
}
四、Exists Query
Exists Query(存在性查詢),用于檢索字段存在的文檔。通俗地說:它就是再問"這個字段在文檔里有沒有值?"
文檔的某個字段可能因為多種原因沒有被索引,原因可能如下:
- 該字段的可能是 null 或者 [],因為 Elasticsearch 不會為 null 或空數組的字段建立索引。也就是說,雖然字段在 _source 中存在,但在索引中根本沒有它的信息,exists 查詢時就不會命中
- 在 mapping 設置時,針對該字段做了如下操作:
- index: false【關閉倒排索引】 且 doc_values: false【關閉列式存儲】,這種字段也不會被索引
- ignore_above: xxx(number) ,該字段是 keyword 類型字段中常見的參數,用來忽略過長的字符串,如果超出限制,也不會被索引
- ignore_malformed: xxx(bool),字段的值格式錯誤,但映射中設置了 ignore_malformed,也就是當我們傳入了格式錯誤的字段值(比如給整數字段傳了字符串),如果該設置為true,Elasticsearch 會忽略該字段的索引,而不是拋出錯誤。
4.1、RESTful API 示例
PUT my_index_00003
{"mappings": {"properties": {"username": {"type": "keyword"},"age": {"type": "long","index": false,"doc_values": false}}}
}PUT my_index_00003/_doc/1
{"username": "markuszhang","age": 26
}
PUT my_index_00003/_doc/2
{"username": "luna","age": 25
}// 查不到值,因為 age 字段關閉了 index 和 doc_values
GET my_index_00003/_search
{"query": {"term": {"age": {"value": 25}}}
}GET my_index_00003/_search
{"query": {"bool": {"must_not": [{"exists": {"field": "age"}}]}}
}GET my_index_00003/_search
{"query": {"exists": {"field": "username"}}
}
五、Fuzzy Query
Fuzzy Query 是用來處理拼寫錯誤或不精確匹配的查詢類型。它基于 Levenshtein 編輯距離,允許在查詢字符串和被匹配詞之間存在一定程度的差異(插入、刪除、替換、轉置字符)。例如:查詢詞是 “roam”,它可以模糊匹配 “foam”,“roams”,“room” 等。
5.1、相關參數介紹
{"query": {"fuzzy": {"field": {"value": "xxx","fuzziness": "AUTO","max_expansions": 50,"prefix_length": 0,"transpositions": true,"rewrite": "constant_score"}}}
}
- field: 需要查詢的字段
- value: 需要查詢的 term
- fuzziness: 允許匹配的最大編輯距離
- max_expansions: 最大擴展詞數量的限制(根據 fuzziness 生成若干個變體詞去倒排索引進行查詢,這個參數就是用來限制變體詞的數量,默認50)
- prefix_length: 帶前綴長度限制的模糊匹配,設置為0 表示不要求前綴必須精確匹配
- transpositions: 用來控制是否允許兩個相鄰字符的位置調換,也算作一次編輯操作
- rewrite: 當使用 fuzzy 查詢時,它會生成多個可能匹配的 term,然后使用布爾查詢來組合這些 term 進行匹配,該參數決定了這個布爾查詢的類型和執行方式,會影響查詢性能、精度、匹配方式
- 可選的模式如下:
- constant_score: 默認方式,把所有的匹配的 term 作為 filter,不計算得分
- scoring_boolean: 用 should 條件組合匹配 term,計算得分
- constant_score_boolean: 和 scoring_boolean 類似,但不計算得分,性能更好
- top_terms_N: 只使得得分前 N 個詞項參與查詢
- top_terms_boost_N: 和 top_terms_N 類似,但使用原始分值作為 boost
- top_terms_blended_freqs_N: 綜合考慮詞頻,得分更精細(Lucene 支持)
- 可選的模式如下:
5.2、RESTful API 示例
PUT my_index_00004
{"mappings": {"properties": {"username": {"type": "text"}}}
}PUT my_index_00004/_doc/1
{"username": "markuszhang"
}GET my_index_00004/_search
{"query": {"fuzzy": {"username": {"value": "makuszhang","fuzziness": 1,"prefix_length": 1,"rewrite": "constant_score"}}}
}
六、IDs Query
基于文檔 id 進行查詢
GET my_index_00003/_search
{"query": {"ids": {"values": [1,2]}}
}
七、Prefix Query
前綴查詢,即指定前綴,檢索符合條件的文檔
7.1、相關參數介紹
{"query": {"prefix": {"field": {"value": "prefix"}}}
}
- field: 需要檢索的字段
- value: 需要檢索的起始字符
- rewrite: 同 Fuzzy Query 中的參數
- case_insensitive: 在 7.10.0 版本添加,是否考慮大小寫
7.2、RESTful API 示例
GET my_index_00004/_search
{"query": {"prefix": {"username": {"value": "Markus","case_insensitive": true}}}
}
八、Range Query
范圍查詢,指定 terms 的范圍,返回符合條件的文檔
8.1、相關參數介紹
{"query": {"range": {"age": {"gte": 10,"lte": 20,"boost": 2.0}}}
}
- gt: 大于
- gte: 大于等于
- lt: 小于
- lte: 小于等于
- format: 將value值轉換為某種格式,es 默認使用的是 日期格式
- relation: 如果字段是一個 range 類型,則這塊會有幾個查詢模式
- INTERSECTS(默認),即有交集就算符合條件
- CONTAINS,文檔范圍完全包含查詢范圍
- WITHIN, 文檔范圍完全被查詢范圍包含
- time_zone: 時區
- boost: 對此查詢條件做加降權
8.2、RESTful API 示例
PUT my_index_00005
{"mappings": {"properties": {"username": {"type": "keyword"},"age": {"type": "long"}}}
}PUT my_index_00005/_doc/1
{"username": "markuszhang","age": 26
}
PUT my_index_00005/_doc/2
{"username": "luna","age": 25
}GET my_index_00005/_search
{"query": {"range": {"age": {"gte": 26}}}
}
九、Regexp Query
正則表達式匹配查詢,返回符合正則表達式的文檔
9.1、相關參數介紹
{"query": {"regexp": {"field": {"value": "k.*y","flags": "ALL","case_insensitive": true,"max_determinized_states": 10000,"rewrite": "constant_score_blended"}}}
}
- field: 需要檢索的字段
- value: 正則表達式,Elasticsearch 默認限制 1000 characters,我們可以通過 index.max_regex_length setting 設置
- 正則查詢的性能受正則表達式影響,為提升性能,盡量避免直接使用通配符,例如 ., .?+,沒有前綴或者后綴。
- flags: 可以啟用(或組合啟用)不同的 正則表達式特性
- case_insensitive: 是否考慮大小寫
- max_determinized_states: 自動機狀態數,默認10000,避免出現性能問題
- rewrite: 同 Fuzzy Query 中的參數
9.2、RESTful API 示例
GET my_index_00005/_search
{"query": {"regexp": {"username": "markus.*"}}
}
十、Wildcard Query
通配符查詢,與 regexp query相比,wildcard
查詢語法簡單、性能更高,適用于常見的通配搜索。
10.1、相關參數介紹
{"query": {"wildcard": {"field": {"value": "ki*y","boost": 1.0,"rewrite": "constant_score_blended"}}}
}
- field: 要查詢的字段
- boost: 相關性算法加降權
- case_insensitive: 大小寫敏感
- rewrite: 同 Fuzzy Query 中的參數
- value: 帶通配符的 terms
- ? 表示匹配任意單個字符串
- * 表示匹配0或任意個字符,包含空字符
- 需要注意,避免使用 * or ? 作為 term 的起始字符,這會增加查詢匹配 term 的次數和降低查詢性能
- wildcard: 和 value 對應,是 value 參數的別名,如果 value 和 wildcard 同時被指定,會選擇 request body 中最后一個參數所指定的 term 進行查詢
使用 * 的通配符查詢可能會消耗大量資源,特別是前綴是 * 的查詢。為了提高查詢性能,應盡量減少使用這種方式,并考慮其他替代方案,比如使用 n-gram 分詞器。雖然 n-gram 能讓搜索更高效,但會導致索引變大。為了更好的性能和準確性,建議將 wildcard 查詢和其他查詢(如 match 或 bool)組合使用,先縮小候選結果,再進行通配匹配
10.2、RESTful API 示例
GET my_index_00005/_search
{"query": {"wildcard": {"username": "markus*hang"}}
}