這個(gè)才是實(shí)際最常用的方式盛龄,可以構(gòu)建復(fù)雜的查詢條件。
對(duì)于復(fù)雜的查詢芳誓,最好都先校驗(yàn)下余舶,看有沒有報(bào)錯(cuò)。
GET /product_index/_validate/query?explain
{
"query": {
"match": {
"product_name": "toothbrush"
}
}
}
DSL 簡(jiǎn)單用法
查詢所有的商品:
GET /product_index/_search
{
"query": {
"match_all": {}
}
}
查詢商品名稱包含 toothbrush 的商品锹淌,同時(shí)按照價(jià)格降序排序:
GET /product_index/_search
{
"query": {
"match": {
"product_name": "toothbrush"
}
},
"sort": [
{
"price": "desc"
}
]
}
分頁(yè)查詢商品:
GET /product_index/_search
{
"query": {
"match_all": {}
},
"from": 0, ## 從第幾個(gè)商品開始查匿值,最開始是 0
"size": 1 ## 要查幾個(gè)結(jié)果
}
指定查詢結(jié)果字段(field)
GET /product_index/product/_search
{
"query": {
"match_all": {}
},
"_source": [
"product_name",
"price"
]
}
搜索商品名稱包含 toothbrush,而且售價(jià)大于 400 元赂摆,小于 700 的商品
GET /product_index/_search
{
"query": {
"bool": {
"must": {
"match": {
"product_name": "toothbrush"
}
},
"filter": {
"range": {
"price": {
"gt": 400,
"lt": 700
}
}
}
}
}
}
full-text search 全文檢索挟憔,倒排索引
索引中只要有任意一個(gè)匹配拆分后詞就可以出現(xiàn)在結(jié)果中,只是匹配度越高的排越前面
比如查詢:PHILIPS toothbrush烟号,會(huì)被拆分成兩個(gè)單詞:PHILIPS 和 toothbrush绊谭。只要索引中 product_name 中只要含有任意對(duì)應(yīng)單詞,都會(huì)在搜索結(jié)果中褥符,只是如果有數(shù)據(jù)同時(shí)含有這兩個(gè)單詞龙誊,則排序在前面。
GET /product_index/_search
{
"query": {
"match": {
"product_name": "PHILIPS toothbrush"
}
}
}
phrase search 短語搜索
索引中必須同時(shí)匹配拆分后詞就可以出現(xiàn)在結(jié)果中
比如查詢:PHILIPS toothbrush喷楣,會(huì)被拆分成兩個(gè)單詞:PHILIPS 和 toothbrush趟大。索引中必須有同時(shí)有這兩個(gè)單詞的才會(huì)在結(jié)果中。
GET /product_index/_search
{
"query": {
"match_phrase": {
"product_name": "PHILIPS toothbrush"
}
}
}
Highlight Search 高亮搜索
給匹配拆分后的查詢?cè)~增加高亮的 html 標(biāo)簽铣焊,比如這樣的結(jié)果:"<em>PHILIPS</em> <em>toothbrush</em> HX6730/02"
GET /product_index/_search
{
"query": {
"match": {
"product_name": "PHILIPS toothbrush"
}
},
"highlight": {
"fields": {
"product_name": {}
}
}
}
range 用法逊朽,查詢數(shù)值、時(shí)間區(qū)間:
GET /product_index/_search
{
"query": {
"range": {
"price": {
"gte": 30.00
}
}
}
}
match 用法(與 term 進(jìn)行對(duì)比):
查詢的字段內(nèi)容是進(jìn)行分詞處理的曲伊,只要分詞的單詞結(jié)果中叽讳,在數(shù)據(jù)中有滿足任意的分詞結(jié)果都會(huì)被查詢出來
GET /product_index/_search
{
"query": {
"match": {
"product_name": "PHILIPS toothbrush"
}
}
}
match 還有一種情況,就是必須滿足分詞結(jié)果中所有的詞坟募,而不是像上面岛蚤,任意一個(gè)就可以的。(這個(gè)常見懈糯,所以很重要)
看下面的 JSON 其實(shí)你也可以猜出來涤妒,其實(shí)上面的 JSON 和下面的 JSON 本質(zhì)是:operator 的差別,上面是 or赚哗,下面是 and 關(guān)系她紫。
GET /product_index/_search
{
"query": {
"match": {
"product_name": {
"query": "PHILIPS toothbrush",
"operator": "and"
}
}
}
}
match 還還有一種情況硅堆,就是必須滿足分詞結(jié)果中百分比的詞,比如搜索詞被分成這樣子:java 程序員 書 推薦贿讹,這里就有 4 個(gè)詞渐逃,假如要求 50% 命中其中兩個(gè)詞就返回,我們可以這樣:
當(dāng)然民褂,這種需求也可以用 must茄菊、must_not、should 匹配同一個(gè)字段進(jìn)行組合來查詢
GET /product_index/_search
{
"query": {
"match": {
"product_name": {
"query": "java 程序員 書 推薦",
"minimum_should_match": "50%"
}
}
}
}
multi_match 用法:
查詢 product_name 和 product_desc 字段中赊堪,只要有:toothbrush 關(guān)鍵字的就查詢出來买羞。
GET /product_index/_search
{
"query": {
"multi_match": {
"query": "toothbrush",
"fields": [
"product_name",
"product_desc"
]
}
}
}
multi_match 跨多個(gè) field 查詢,表示查詢分詞必須出現(xiàn)在相同字段中雹食。
GET /product_index/_search
{
"query": {
"multi_match": {
"query": "PHILIPS toothbrush",
"type": "cross_fields",
"operator": "and",
"fields": [
"product_name",
"product_desc"
]
}
}
}
match_phrase 用法(短語搜索)(與 match 進(jìn)行對(duì)比):
對(duì)這個(gè)查詢?cè)~不進(jìn)行分詞,必須完全匹配查詢?cè)~才可以作為結(jié)果顯示期丰。
GET /product_index/_search
{
"query": {
"match_phrase": {
"product_name": "PHILIPS toothbrush"
}
}
}
match_phrase + slop(與 match_phrase 進(jìn)行對(duì)比):
在說 slop 的用法之前群叶,需要先說明原數(shù)據(jù)是:PHILIPS toothbrush HX6730/02,被分詞后至少有:PHILIPS钝荡,toothbrush街立,HX6730 三個(gè) term。
match_phrase 的用法我們上面說了埠通,按理說查詢的詞必須完全匹配才能查詢到赎离,PHILIPS HX6730 很明顯是不完全匹配的。
查詢的關(guān)鍵字分詞后移動(dòng)多少位可以跟 doc 內(nèi)容匹配端辱,移動(dòng)的次數(shù)就是 slop梁剔。所以 HX6730 PHILIPS 其實(shí)也是可以匹配到 doc 的,只是 slop = 5 才行舞蔽。
GET /product_index/_search
{
"query": {
"match_phrase": {
"product_name" : {
"query" : "PHILIPS HX6730",
"slop" : 1
}
}
}
}
match + match_phrase + slop 組合查詢荣病,使查詢結(jié)果更加精準(zhǔn)和結(jié)果更多
但是 match_phrase 性能沒有 match 好,所以一般需要先用 match 第一步進(jìn)行過濾渗柿,然后在用 match_phrase 進(jìn)行進(jìn)一步匹配个盆,并且重新打分,這里又用到了:rescore朵栖,window_size 表示對(duì)前 10 個(gè)進(jìn)行重新打分
下面第一個(gè)是未重新打分的颊亮,第二個(gè)是重新打分的
GET /product_index/_search
{
"query": {
"bool": {
"must": {
"match": {
"product_name": {
"query": "PHILIPS HX6730"
}
}
},
"should": {
"match_phrase": {
"product_name": {
"query": "PHILIPS HX6730",
"slop": 10
}
}
}
}
}
}
重新打分:
GET /product_index/_search
{
"query": {
"match": {
"product_name": "PHILIPS HX6730"
}
},
"rescore": {
"window_size": 10,
"query": {
"rescore_query": {
"match_phrase": {
"product_name": {
"query": "PHILIPS HX6730",
"slop": 10
}
}
}
}
}
}
match_phrase_prefix 用法(不常用)
一般用于類似 Google 搜索框,關(guān)鍵字輸入推薦
max_expansions 用來限定最多匹配多少個(gè) term陨溅,優(yōu)化性能
但是總體來說性能還是很差终惑,因?yàn)檫€是會(huì)掃描整個(gè)倒排索引。推薦用 edge_ngram 做該功能
GET /product_index/_search
{
"query": {
"match_phrase_prefix": {
"product_name": "PHILIPS HX",
"slop": 5,
"max_expansions": 20
}
}
}
term 用法
1 基本用法
(與 match 進(jìn)行對(duì)比: term 一般用在不分詞字段上的声登,因?yàn)樗峭耆ヅ洳樵兒菰В绻樵兊淖侄问欠衷~字段就會(huì)被拆分成各種分詞結(jié)果揣苏,和完全查詢的內(nèi)容就對(duì)應(yīng)不上了。):
所以自己設(shè)置 mapping 的時(shí)候有些不分詞的時(shí)候就最好設(shè)置不分詞件舵。
其實(shí) Elasticsearch 5.X 之后給 text 類型的分詞字段卸察,又默認(rèn)新增了一個(gè)子字段 keyword,這個(gè)字段的類型就是 keyword铅祸,是不分詞的坑质,默認(rèn)保留 256 個(gè)字符。假設(shè) product_name 是分詞字段临梗,那有一個(gè) product_name.keyword 是不分詞的字段涡扼,也可以用這個(gè)子字段來做完全匹配查詢。
GET /product_index/_search
{
"query": {
"term": {
"product_name": "PHILIPS toothbrush"
}
}
}
GET /product_index/_search
{
"query": {
"constant_score": {
"filter":{
"term": {
"product_name": "PHILIPS toothbrush"
}
}
}
}
}
terms 用法盟庞,類似于數(shù)據(jù)庫(kù)的 in
GET /product_index/_search
{
"query": {
"constant_score": {
"filter": {
"terms": {
"product_name": [
"toothbrush",
"shell"
]
}
}
}
}
}
query 和 filter 差異
只用 query:
GET /product_index/_search
{
"query": {
"bool": {
"must": [
{
"terms": {
"product_name": [
"PHILIPS",
"toothbrush"
]
}
},
{
"range": {
"price": {
"gt": 12.00
}
}
}
]
}
}
}
只用 filter:
下面語句使用了 constant_score 查詢吃沪,它可以包含查詢或過濾,為任意一個(gè)匹配的文檔指定評(píng)分 1 什猖,忽略 TF/IDF 信息票彪,不需再計(jì)算評(píng)分。
也還可以指定分?jǐn)?shù):https://www.elastic.co/guide/cn/elasticsearch/guide/current/ignoring-tfidf.html
GET /product_index/_search
{
"query": {
"constant_score": {
"filter": {
"range": {
"price": {
"gte": 30.00
}
}
}
}
}
}
query 和 filter 一起使用的話不狮,filter 會(huì)先執(zhí)行降铸,看本文下面的:多搜索條件組合查詢
官網(wǎng)文檔:https://www.elastic.co/guide/en/elasticsearch/guide/current/_queries_and_filters.html
從搜索結(jié)果上看:
filter,只查詢出搜索條件的數(shù)據(jù)摇零,不計(jì)算相關(guān)度分?jǐn)?shù)
query推掸,查詢出搜索條件的數(shù)據(jù),并計(jì)算相關(guān)度分?jǐn)?shù)驻仅,按照分?jǐn)?shù)進(jìn)行倒序排序
從性能上看:
filter(性能更好谅畅,無排序),無需計(jì)算相關(guān)度分?jǐn)?shù)雾家,也就無需排序铃彰,內(nèi)置的自動(dòng)緩存最常使用查詢結(jié)果的數(shù)據(jù)
緩存的東西不是文檔內(nèi)容,而是 bitset芯咧,具體看:https://www.elastic.co/guide/en/elasticsearch/guide/2.x/_finding_exact_values.html#_internal_filter_operation
query(性能較差牙捉,有排序),要計(jì)算相關(guān)度分?jǐn)?shù)敬飒,按照分?jǐn)?shù)進(jìn)行倒序排序邪铲,沒有緩存結(jié)果的功能
filter 和 query 一起使用可以兼顧兩者的特性,所以看你業(yè)務(wù)需求无拗。
多搜索條件組合查詢(最常用)
bool 下包括:must(必須匹配带到,類似于數(shù)據(jù)庫(kù)的 =),must_not(必須不匹配英染,類似于數(shù)據(jù)庫(kù)的 !=)揽惹,should(沒有強(qiáng)制匹配被饿,類似于數(shù)據(jù)庫(kù)的 or),filter(過濾)
GET /product_index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"product_name": "PHILIPS toothbrush"
}
}
],
"should": [
{
"match": {
"product_desc": "刷頭"
}
}
],
"must_not": [
{
"match": {
"product_name": "HX6730"
}
}
],
"filter": {
"range": {
"price": {
"gte": 33.00
}
}
}
}
}
}
嵌套形式:
GET /product_index/_search
{
"query": {
"bool": {
"should": [
{
"term": {
"product_name": "飛利浦"
}
},
{
"bool": {
"must": [
{
"term": {
"product_desc": "刷頭"
},
"term": {
"price": 30
}
}
]
}
}
]
}
}
}
should 有一個(gè)特殊性搪搏,如果組合查詢中沒有 must 條件狭握,那么 should 中必須至少匹配一個(gè)。我們也還可以通過 minimum_should_match 來限制它匹配更多個(gè)疯溺。
GET /product_index/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"product_name": "java"
}
},
{
"match": {
"product_name": "程序員"
}
},
{
"match": {
"product_name": "書"
}
},
{
"match": {
"product_name": "推薦"
}
}
],
"minimum_should_match": 3
}
}
}
下面還用到自定義排序论颅。
排序最好別用到字符串字段上。因?yàn)樽址侄螘?huì)進(jìn)行分詞囱嫩,Elasticsearch 默認(rèn)是拿分詞后的某個(gè)詞去進(jìn)行排序恃疯,排序結(jié)果往往跟我們想象的不一樣。解決這個(gè)辦法是在設(shè)置 mapping 的時(shí)候墨闲,多個(gè)這個(gè)字段設(shè)置一個(gè) fields raw今妄,讓這個(gè)不進(jìn)行分詞,然后查詢排序的時(shí)候使用這個(gè) raw鸳碧,
具體看這里:https://www.elastic.co/guide/cn/elasticsearch/guide/current/multi-fields.html
GET /product_index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"product_name": "PHILIPS toothbrush"
}
}
],
"should": [
{
"match": {
"product_desc": "刷頭"
}
}
],
"filter": {
"bool": {
"must": [
{
"range": {
"price": {
"gte": 33.00
}
}
},
{
"range": {
"price": {
"lte": 555.55
}
}
}
],
"must_not": [
{
"term": {
"product_name": "HX6730"
}
}
]
}
}
}
},
"sort": [
{
"price": {
"order": "desc"
}
}
]
}
boost 用法(默認(rèn)是 1)蛙奖。
在搜索精準(zhǔn)度的控制上,還有一種需求杆兵,比如搜索:PHILIPS toothbrush,要比:Braun toothbrush 更加優(yōu)先仔夺,我們可以這樣:
GET /product_index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"product_name": "toothbrush"
}
}
],
"should": [
{
"match": {
"product_name": {
"query": "PHILIPS",
"boost": 4
}
}
},
{
"match": {
"product_name": {
"query": "Braun",
"boost": 3
}
}
}
]
}
}
}
dis_max 用法琐脏,也稱作:best fields 策略。
由于查詢關(guān)鍵字是會(huì)被分詞的缸兔,默認(rèn) query bool 查詢多個(gè)字段的語法時(shí)候日裙,每個(gè)字段匹配到一個(gè)或多個(gè)的時(shí)候分?jǐn)?shù)比:一個(gè)字段匹配到查詢分詞的所有結(jié)果的分?jǐn)?shù)來的大。但是對(duì)于我們來講這樣的不夠精準(zhǔn)的惰蜜。所以我們希望查詢字段中昂拂,匹配的關(guān)鍵字越多排序越靠前,而不是每個(gè)字段查詢了一個(gè)分詞就排前抛猖,我們可以使用 dis_max格侯。
但是使用 dis_max,一般還不夠财著,建議再加上 tie_breaker联四。
tie_breaker 是一個(gè)小數(shù)值,在 0~1 之間用來將其他查詢結(jié)果分?jǐn)?shù)撑教,乘以 tie_breaker 的值朝墩,然后再綜合與 dis_max 最高分?jǐn)?shù)的的分?jǐn)?shù)一起進(jìn)行計(jì)算。除了取 dis_max 的最高分以外伟姐,還會(huì)考慮其他的查詢結(jié)果的分?jǐn)?shù)收苏。
在 dis_max 基礎(chǔ)上亿卤,為了增加精準(zhǔn),我們還可以加上:boost鹿霸、minimum_should_match 等相關(guān)參數(shù)排吴。其中 minimum_should_match 比較常用,因?yàn)椴樵冏侄蔚姆衷~中如果只有一個(gè)分詞查詢上了這種結(jié)果基本是沒啥用的杜跷。
官網(wǎng)資料:https://www.elastic.co/guide/en/elasticsearch/guide/current/_best_fields.html
GET /product_index/_search
{
"query": {
"dis_max": {
"queries": [
{
"match": {
"product_name": "PHILIPS toothbrush"
}
},
{
"match": {
"product_desc": "iphone shell"
}
}
],
"tie_breaker": 0.2
}
}
}
GET /product_index/_search
{
"query": {
"dis_max": {
"queries": [
{
"match": {
"product_name": {
"query": "PHILIPS toothbrush",
"minimum_should_match": "50%",
"boost": 3
}
}
},
{
"match": {
"product_desc": {
"query": "iphone shell",
"minimum_should_match": "50%"傍念,
"boost": 2
}
}
}
],
"tie_breaker": 0.3
}
}
}
prefix 前綴搜索(性能較差,掃描所有倒排索引)
比如有一個(gè)不分詞字段 product_name葛闷,分別有兩個(gè) doc 是:iphone-6憋槐,iphone-7。我們搜索 iphone 這個(gè)前綴關(guān)鍵字就可以搜索到結(jié)果
GET /product_index/_search
{
"query": {
"prefix": {
"product_name": {
"value": "iphone"
}
}
}
}
通配符搜索(性能較差淑趾,掃描所有倒排索引)
GET /product_index/_search
{
"query": {
"wildcard": {
"product_name": {
"value": "ipho*"
}
}
}
}
正則搜索(性能較差阳仔,掃描所有倒排索引)
GET /product_index/product/_search
{
"query": {
"regexp": {
"product_name": "iphone[0-9].+"
}
}
}
fuzzy 糾錯(cuò)查詢
參數(shù) fuzziness 默認(rèn)是 2,表示最多可以糾錯(cuò)兩次扣泊,但是這個(gè)值不能很大近范,不然沒效果。一般 AUTO 是自動(dòng)糾錯(cuò)延蟹。
下面的關(guān)鍵字漏了一個(gè)字母 o评矩。
GET /product_index/_search
{
"query": {
"match": {
"product_name": {
"query": "PHILIPS tothbrush",
"fuzziness": "AUTO",
"operator": "and"
}
}
}
}
其他資料輔助
————————————————
版權(quán)聲明:本文為CSDN博主「baofenny」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議阱飘,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明斥杜。
原文鏈接:https://blog.csdn.net/jiaminbao/article/details/80105636