Elasticsearch 7提供了多種檢索文檔的方式,我們可以通過Restful API的方式來搜尋索引中的文檔。Elasticsearch的搜尋可以分為以下幾個類型:
- 全文搜尋
- 詞項搜尋
- 複合搜尋
- 嵌套搜尋
- 位置搜尋
- 特殊搜尋
本文例子采用測試文檔庫shakespeare,下載下傳連結https://www.elastic.co/guide/en/kibana/7.2/tutorial-build-dashboard.html 。
1 全文搜尋
全文搜尋通常用于搜尋文本字段,需要使用者提供關鍵字來完成。
1.1 match搜尋
match搜尋會對使用者給出的關鍵詞進行解析,首先會将其進行分詞處理,分詞後查詢語句中的任意一個詞項被比對,文檔就會檢索到。其子參數包含:
-
(必填):搜尋關鍵文本query
-
(可選):分詞器,用于将analyzer
中的文本轉換為一個個詞項query
-
(可選):使用編輯距離技術進行模糊比對fuzziness
-
:模糊比對的起始單詞數prefix_length
-
(預設為OR):布爾邏輯,用來解釋operator
中的詞項,可選的參數有OR、ANDquery
-
(可選):傳回的文檔需要比對的最小子串數minimum_should_match
示例:
GET /shakespeare/_search
{
"query": {
"match": {
"text_entry": {
"query": "apple eye",
"operator": "and"
}
}
}
}
查詢包含
text_entry
字段中包含單詞apple和eye的文檔
1.2 match_phrase搜尋
match_phrase搜尋會首先把
query
進行分詞處理,分詞器可以自定義,同時文檔還需滿足以下條件才能被比對:
- 分詞後所有詞項都要出現在該字段中
- 字段中所有的詞項順序要一緻
如果将上述示例改為match_phrase,那麼隻有eye在apple後面的文檔才可以被搜尋到。
1.3 match_phrase_prefix搜尋
和match_phrase搜尋類似,隻不過match_phrase_prefix支援詞項的字首比對,例如:
GET /shakespeare/_search
{
"query": {
"match_phrase_prefix": {
"text_entry": {
"query": "app"
}
}
}
}
那麼隻會查找出某個詞項的字首為app的文檔。
1.4 multi_match搜尋
multi_match搜尋是match的更新版,可以用于搜尋多個字段,例如:
GET /shakespeare/_search
{
"query": {
"multi_match": {
"query": "apple",
"fields": ["text_entry", "speaker"]
}
}
}
上述查詢語句會在
text_entry
和
speaker
字段中查詢包含單詞apple的文檔
1.5 match_bool_prefix搜尋
match_bool_prefix搜尋于Elasticsearch 7.0推出,它将輸入的文本通過指定的分詞器來處理多個
term
,然後基于這些
term
進行bool query,除了最後一個
term
使用字首查詢,其它都是使用term_query。
GET /shakespeare/_search
{
"query": {
"match_bool_prefix": {
"query": "away as nim",
}
}
}
上述示例相當于查詢包含單詞away、as,并且有單詞以nim開頭的文檔。
2 詞項搜尋
全文搜尋在查詢前會分析
query
字元串,而詞項搜尋一般用于對存儲的詞項進行精确搜尋,通常用于一些結構化資料,例如數字、枚舉類型、日期類型等。
2.1 term
最基本的詞項搜尋,用于檢索出某個
text
字段中包含指定單詞的文檔。例如:
GET /shakespeare/_search
{
"query": {
"term": {
"text_entry": {
"value": "apple",
"boost": 1.0
}
}
}
}
上述請求可以查找出
text_entry
字段中包含單詞apple的文檔。
value
參數為需要查找的詞項;
boost
用來減少或增加相關性系數,預設為1.0,大于1.0會增加其相關性,小于1.0會減少其相關性。
2.2 terms
terms
可以用來查找
text
字段中包含一個或多個指定單詞的文檔,例如:
GET /shakespeare/_search
{
"query": {
"terms": {
"text_entry": [
"eye","apple"
]
}
}
}
上述請求會查找出
text_entry
字段中滿足以下要求的文檔:
- 包含單詞eye,不包含單詞apple
- 包含單詞apple,不包含單詞eye
- 包含單詞eye和apple
同樣,terms也可以使用
boost
來減少或增加相關性系數。
2.3 regexp
regexp
檢索可以查找出包含滿足正規表達式單詞的文檔,例如:
GET /shakespeare/_search
{
"query": {
"regexp": {
"text_entry": "pa.*"
}
}
}
上述請求會查找出
text_entry
字段中包含以pa開頭的單詞的文檔。
需要注意
regexp
檢索不支援包含
^
(行的開頭)或
$
(行的結尾)的正規表達式。
regexp
檢索還支援以下幾個參數:
-
:啟用正規表達式可選運算符flags
-
:查詢所需的最大自動機狀态數,用于限制過于複雜的正規表達式,預設10000。max_determinized_states
2.4 prefix
prefix
檢索可以查找出包含指定字元串開頭的單詞的文檔,例如:
GET /shakespeare/_search
{
"query": {
"prefix": {
"text_entry": {
"value": "par"
}
}
}
}
上述請求會查找出包含以par開頭的單詞的文檔。
2.5 range
range
檢索可以用于查詢指定字段中在指定範圍内的文檔,例如:
GET /shakespeare/_search
{
"query": {
"range": {
"line_id": {
"gte": 160,
"lte": 170
}
}
}
}
上述請求可以查找出
line_id
字段大于等于160,小于等于170的文檔。此外還有
gt
和
lt
,用于表示大于和小于符号。
2.6 wildcard
wildcard
檢索用于單詞的通配符檢索,相當于一個簡化版本的
regexp
檢索,
?
用于比對一個任意字元,
*
号用于比對0個或者多個任意字元,相當于正則的
.*
。例如:
GET /shakespeare/_search
{
"query": {
"wildcard": {
"text_entry": {
"value": "pre*"
}
}
}
}
上述請求可以查找出
text_entry
字段中包含以pre開頭的單詞的文檔。此外
wildcard
也支援
boost
參數,作用類似。
2.7 fuzzy
fuzzy
檢索用于詞項的近似檢索,例如
applx
可以檢索出包含
apple
單詞的文檔,兩個單詞的相似度通過編輯距離算法(Levenshtein)确定。例如:
GET /shakespeare/_search
{
"query": {
"fuzzy": {
"text_entry": "applx"
}
}
}
上述請求可以查找出包含近似applx單詞的文檔,例如包含apple、apply的文檔等。
fuzzy
查詢效率不高,需要消耗的資源比較大。
3 複合查詢
複合查詢就是将一些簡單的查詢組合在一起作為查詢條件進行文檔檢索。
3.1 constant_score
constant_score
檢索可以包裝一個其它類型的查詢,并傳回比對過濾器中的查詢條件且具備相同評分的文檔。
GET /shakespeare/_search
{
"query": {
"constant_score": {
"filter": {
"term": {
"text_entry": "apple"
}
},
"boost": 1.2
}
}
}
上述查詢條件會傳回包含apple單詞的文檔,并且評分都是1.2
3.2 bool
bool
查詢可以将任意多個簡單查詢組合在一起,使用
must
、
should
、
must_not
、
filter
選項來表示簡單查詢之間的邏輯:
-
:文檔必須要比對must
下的查詢條件must
-
:文檔可以比對也可以不比對should
下的查詢條件,比對的文檔評分會更高should
-
:比對該選項下的查詢條件的文檔會被過濾,不會傳回must_not
-
:和filter
類似,不同的是must
中的條件不會參與評分。filter
例如:
GET /shakespeare/_search
{
"query": {
"bool": {
"must": [{
"term": {
"text_entry": {
"value": "must"
}
}}
],
"should": [{
"term": {
"text_entry": {
"value": "have"
}
}}
]
}
}
}
注意
must
、
should
、
must_not
、
filter
的值都是JSON數組,可以添加多個查詢條件,包括詞項搜尋和全文搜尋。
3.3 function_score
function_score
可以修改查詢的文檔的得分,使用者需要定義一個查詢和一到多個評分函數,評分函數會對查詢到的每個文檔分别計算其得分。
例如:
GET /shakespeare/_search
{
"query": {
"function_score": {
"query": {
"match": {
"text_entry": "apple"
}
},
"script_score": {
"script": {
"inline": "Math.sqrt(doc['line_id'].value)"
}
}
}
}
}
上述請求可以查找出
text_entry
包含apple的文檔,并且評分按照
line_id
的開方計算。
function_score
查詢方式内嵌了多種函數和查詢方法,可以參照官方文檔了解更多。
3.4 dis_max
dis_max
檢索(Disjucation Max Query)和
bool
檢索有聯系也有差別,
dis_max
支援多并發查詢,可以傳回與任意查詢條件子句比對的任何文檔類型。和
bool
檢索不同的是,
dis_max
查詢隻使用最佳比對查詢條件的分數:
GET /shakespeare/_search
{
"query": {
"dis_max": {
"tie_breaker": 0.7,
"boost": 1.2,
"queries": [
{ "term": { "text_entry": "apple" } },
{ "term": { "text_entry": "watch" } }
]
}
}
}
3.5 boosting
boosting查詢适用于需要對評分進行調整的場景,它會把兩個查詢封裝在一起并降低其中一個查詢條件的評分,例如:
GET /shakespeare/_search
{
"query": {
"boosting": {
"positive": {
"match": {
"text_entry": "apple"
}
},
"negative": {
"range": {
"line_id": {
"gte": 0,
"lte": 10000
}
}
},
"negative_boost": 0.2
}
}
}
上述查詢條件中會降低
line_id
在0到10000之間的文檔的評分,會降低到原先的0.2倍。