檢索和過濾區別
1)查詢器(query):
- 先查詢符合搜索條件的文檔, 然後計算每個文檔對於搜索條件的相關度分數, 再根據評分倒序排序.
2)過濾器(filter):
- 只根據搜索條件過濾出符合的文檔, 將這些文檔的評分固定爲1, 忽略TF/IDF信息, 不計算相關度分數;
- 有cache
- filter 性能更好, 無排序
3)注意:filter和query一起使用時, 會先執行filter.
4)場景:
- 業務關心的、需要根據匹配的相關度進行排序的搜索條件 放在
query
中;
- 業務不關心、不需要根據匹配的相關度進行排序的搜索條件 放在
filter
中.
全文檢索
1、分詞全文檢索【match】,對會先對query進行分詞,只要文檔裏面包含一個query中一個詞就會被搜出來
POST bank/_search { "query":{ "match":{ "address":{ "query":"Sedgwick Street aa bb", "operator":"or", "minimum_should_match":2 } } } } //operator:用來控制match查詢匹配詞條的邏輯條件,默認值是or,如果設置爲and,表示查詢滿足所有條件; //minimum_should_match:當operator參數設置爲or時,該參數用來控制應該匹配的分詞的最少數量;
2、短語檢索【macth_phrase】,也會對query進行分詞,但一個文檔必須包含query裏面所有的詞纔會被搜出來
POST bank/_search { "query": { "match_phrase": {//表示"query": "Sedgwick Street"中兩者同時出現 "address": {//地址屬性 "query": "Sedgwick Street", "slop": 3//可選,中間可以有<3個其他的單詞 } } } }
3、短語前綴檢索【match_phrase_prefix】,除了把查詢文本的最後一個分詞只做前綴匹配之外,match_phrase_prefix和match_phrase查詢基本一樣,參數 max_expansions 控制最後一個單詞會被重寫成多少個前綴,也就是,控制前綴擴展成分詞的數量,默認值是50。擴展的前綴數量越多,找到的文檔數量就越多;如果前綴擴展的數量太少,可能查找不到相應的文檔,遺漏數據。
POST bank/_search { "query": { "match_phrase_prefix": { "address": { "query": "Sedgwick Street", "max_expansions": 10//max_expansions 控制最後一個單詞會被重寫成多少個前綴,也就是,控制前綴擴展成分詞的數量,默認值是50 } } } }
4、多字段匹配檢索【multi_match】,在多個字段上執行匹配相同的查詢,涉及到匹配評分的問題
POST bank/_search { "query":{ "multi_match":{ "query": "Sedgwick Street", "fields": ["address","firstname"], "operator": "and" } } } //參數operator設置每個字段的子查詢的匹配分詞的邏輯方式,默認值是or
評分問題
- best_fields
- most_fields
- cross_fields
//我們希望完全匹配的文檔佔的評分比較高,則需要使用best_fields { "query": { "multi_match": { "query": "我的寶馬發動機多少", "type": "best_fields", "fields": [ "tag", "content" ], "tie_breaker": 0.3 } }//匹配"寶馬 發動機"的文檔評分會比較靠前,如果只匹配寶馬的文檔評分乘以0.3的係數 } //我們希望越多字段匹配的文檔評分越高,就要使用most_fields { "query": { "multi_match": { "query": "我的寶馬發動機多少", "type": "most_fields", "fields": [ "tag", "content" ] } } } //我們會希望這個詞條的分詞詞彙是分配到不同字段中的,那麼就使用cross_fields { "query": { "multi_match": { "query": "我的寶馬發動機多少", "type": "cross_fields", "fields": [ "tag", "content" ] } } }
5、支持與、或、非的字符串檢索【query_string】,我們可以通過lucene
的查詢語法編寫一個查詢字符串,然後發送給ES,接收到請求後ES會通過查詢解析器去解析查詢字符串並生成對應的查詢命令。
//單字段的字符串匹配查詢 POST bank/_search { "query": { "query_string": { "default_field": "address", "query": "Sedgwick OR Street"//AND、OR必須大寫 } } } //多字段的字符串匹配查詢 POST bank/_search { "query": { "query_string": { "fields": ["address","firstname"], "query": "Sedgwick AND Street"//不計順序,AND需要大寫 } } }
6、簡化的字符串檢索【simple_query_string】
POST bank/_search { "query": { "simple_query_string": { "fields": ["address"], "query": "(Sedgwick+Street)|Bay" } } } ①類似Query String,但是會忽略錯誤的語法,同時只支持部分查詢語法 ②不支持AND OR NOT,會當作字符串處理 ③Term之間默認的關係是OR,可以指定Operator支持部分邏輯 ④+替代AND | 替代OR -替代NOT
結構化檢索
1、精確匹配檢索【term/terms】
- term: {"field": "value"}
- terms: {"field": ["value1", "value2"]} //相當於sql中的in關鍵字
1)term是代表完全匹配,即不進行分詞器分析,文檔中必須包含整個搜索的詞彙
POST bank/_search { "query": { "term": { "firstname": "hattie" } } }
注意:term檢索搜索的關鍵詞將不會進行分析處理,會根據輸入的搜索詞直接進行去lucene倒排索引裏面去比對,我們都知道數據在檢索時會對要索引的token進行分析處理,其中就包括調用lucene的LowerCaseFilter將token進行小寫處理,所以下面使用bankType進行term類型搜索時傳入【大寫的字母】肯定是查找不到數據的
2)terms //相當於in
POST /forum/article/_search { "query": { "constant_score": { "filter": { "terms": { "tag" : ["java"] } } } } }
2、範圍檢索【range】
POST /bank/_search { "query": { "range" : { "age" : { "gte" : 10, "lte" : 20, "boost" : 2.0 } } } } // gte: 大於或等於 // gt: 大於 // lte: 小於或等於 // lt: 小於 // boost: 設置查詢的提升值,默認爲1.0
3、存在與否【exits】
//返回age不爲null或者沒有值得數據
POST home/_search { "query": { "exists": { "field": "age" } } }
4、前綴檢索【prefix】
//firstname中以H開頭的數據 POST bank/_search { "query": { "prefix": { "firstname": "h"//注意:要小寫,倒排中存的都是小寫 } } } POST bank/_search { "query": { "prefix": { "firstname": { "value": "h" } } } }
5、通配符檢索【wildcard】,允許使用通配符*和?來進行查詢
- *代表0個或多個字符
- ?代表任意1個字符
POST bank/_search { "query": { "wildcard": { "firstname": { "value": "h?ll" } } } }
6、正則檢索【regrxp】
POST bank/_search { "query": { "regexp": { "email": "[a-z]*@qq.com" } } }
7、類型檢索【type】
8、id檢索【ids】
GET /bank/_search { "query": { "ids": { "values": [1,6,20,21] } } }
9、模糊檢索【fuzzy】,返回包含與搜索詞相似的詞的文檔
編輯距離是將一個術語轉換爲另一個術語所需的一個字符更改的次數。 這些更改可以包括:
- 更改字符(box→fox)
- 刪除字符(black→lack)
- 插入字符(sic→sick)
- 轉置兩個相鄰字符(act→cat)
GET /bank/_search { "query": { "fuzzy": { "email": { "value": "[email protected]", "fuzziness": "AUTO", "max_expansions": 50, "prefix_length": 0, "transpositions": true, "rewrite": "constant_score" } } } }
- value,必填項,希望在field中找到的術語
- fuzziness,選填項,匹配允許的最大編輯距離;參數說明
- max_expansions,選填項,創建的最大變體項,默認爲50。應該避免使用較大的值,尤其是當prefix_length參數值爲0時,如果過多,會影響查找性能。
- prefix_length,選填項,創建擴展時保留不變的開始字符數。默認爲0
- transpositions,選填項,指示編輯是否包括兩個相鄰字符串的轉置(ab→ba)。默認爲true
- rewrite,選填項,用於重寫查詢的方法。高級用法。
複合檢索
1、固定得分檢索【constant_score】
//constant_score 爲filter匹配到的結果給到1.2的分數 GET /_search { "query": { "constant_score" : { "filter" : { "term" : { "user" : "kimchy"} }, "boost" : 1.2//不寫默認給到1.0分 } } }
2、bool組合檢索,一種能夠將多查詢組合成單一查詢的查詢方法,貢獻得分來源must&should
它接收以下參數:
1)must,文檔 必須 匹配這些條件才能被包含進來,增加得分。相當於sql中的 and
2)should,如果滿足這些語句中的任意語句,將增加 _score
,否則,無任何影響。它們主要用於修正每個文檔的相關性得分。相當於sql中的or
3)minimun_should_match,指定在該評分以上的文檔才進行返回
4)mast_not,文檔 必須不 匹配這些條件才能被包含進來,不貢獻得分,起過濾作用。相當於sql中的 not
5)filter,必須 匹配,但它以不評分、過濾模式來進行。這些語句對評分沒有貢獻,只是根據過濾標準來排除或包含文檔,有緩存。
示例:
POST _search { "query": { "bool" : { "must" : { "term" : { "user" : "kimchy" } }, "filter": { "term" : { "tag" : "tech" } }, "must_not" : { "range" : { "age" : { "gte" : 10, "lte" : 20 } } }, "should" : [ { "term" : { "tag" : "wow" } }, { "term" : { "tag" : "elasticsearch" } } ], "minimum_should_match" : 1, "boost" : 1.0 } } }
示例2:
{ "bool": { "must": { "match": { "title": "how to make millions" }}, "must_not": { "match": { "tag": "spam" }}, "should": [ { "match": { "tag": "starred" }}, { "range": { "date": { "gte": "2014-01-01" }}} ] } }
Java代碼
BoolQueryBuilder defaultQueryBuilder = QueryBuilders.boolQuery(); defaultQueryBuilder.must(QueryBuilders.matchQuery("title", "how to make millions")) .mustNot(QueryBuilders.matchQuery("tag", "span")) .should(QueryBuilders.matchQuery("tag", "starred")) .should(QueryBuilders.rangeQuery("date").gte("2014-01-01"));
filter用法改造:
{ "bool": { "must": { "match": { "title": "how to make millions" }}, "must_not": { "match": { "tag": "spam" }}, "should": [ { "match": { "tag": "starred" }} ], "filter": { "range": { "date": { "gte": "2014-01-01" }} } }
}
注意filter中的條件不參與評分score排序
3、改變評分檢索
1)Disjunction max
GET /_search { "query": { "dis_max" : { "queries" : [ { "term" : { "title" : "Quick pets" }}, { "term" : { "body" : "Quick pets" }} ], "tie_breaker" : 0.7 } } }
說明:返回一個會多個查詢子句匹配的文檔。如果返回的文檔與多個查詢子句匹配,則dis_max查詢會爲該文檔分配來自所有查詢子句的最高相關性得分,再加上其他得分的和與tie_breaker
的積。
換句話說,您可以使用dis_max搜索來降低最佳匹配子句在相關性得分計算中所佔的比重。
參數:
queries
,必選項。包含一個或多個查詢子句。返回的文檔,必須匹配其中的一個或多個子句。如果一個文檔匹配多個查詢子句,Elasticsearch 將會使用最高的相關性得分。tie_breaker
,選填項。介於0,1.0
之間的浮點數。默認爲0.0
,用於增加,除最佳匹配子句外的其他匹配子句的佔總相關性得分的比重。如果一個文檔匹配多個子句,dis_max查詢將計算該文檔的相關性得分,如下所示:- 從具有最高分數的匹配子句中獲取相關性分數。
- 將任何其他匹配子句的分數乘以該
tie_breaker
值。 - 將最高分數加到相乘的分數上。
2)function_score
3)boosting,給negative匹配到的結果減分
GET /_search { "query": { "boosting" : { "positive" : { "term" : { "text" : "apple" } }, "negative" : { "term" : { "text" : "pie tart fruit crumble tree" } }, "negative_boost" : 0.5 } } }
- positive,所有返回文檔必須匹配該條件
- negative,獲取得分,並將 【得分 * negative_boost】
- negative_boost,將negative匹配的結果降低係數