摘要:百度百科通過模糊搜索可以查詢出存在一定相似度的單詞,那么怎么計算兩個單詞是否有相似度以及相似度的大小呢這就要了解下另外一個概念叫做萊文斯坦距離,是編輯距離的一種。在查詢或者類型的字段時可以看做是萊文斯坦距離。
引言
昨天是感恩節(jié),上幼兒園的女兒在老師的叮囑下,晚上為我和老婆洗了腳(形式上的^_^),還給我們每人端了一杯水。看著孩子一天天的長大,懂事,感覺很開心,話說咱們程序員這么辛苦是為了什么?不就是為了老婆,孩子,熱炕頭,有一個溫暖幸福的家庭,再捎帶著用代碼改變一下世界嗎?想到這里,頓時覺得學習,創(chuàng)作博客的勁頭也的更足了。哈哈,扯遠了,書歸正傳,今天我們來聊聊 Match Query。
Match Query 是最常用的 Full Text Query 。無論需要查詢什么字段, match 查詢都應該會是首選的查詢方式。它既能處理全文字段,又能處理精確字段。
構(gòu)建示例為了能夠在后面能深入理解 Match Query 中的各個屬性的意義,我們先構(gòu)建一個 index 示例(有興趣的同學只要將下面字段粘貼到 sense 中就可以創(chuàng)建)。
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 參數(shù)
match 查詢是一種 bool 類型的查詢。什么意思呢?舉個例子,查詢 people type 的 hobbies 為 football basketball
GET matchtest/people/_search { "query": { "match": { "hobbies": "football basketball" } } }
會將上面的兩個文檔都搜索出來。為什么?上面的查詢其實隱藏了一個默認參數(shù)operator , 它的默認值是 or ,也就是說上面的查詢也可以寫成這種形式
GET matchtest/people/_search { "query": { "match": { "hobbies": { "query": "football basketball", "operator": "or" } } } }
這樣就比較容易理解了,既然是 or 操作符,就表示只要查詢的文檔的 hobbies 字段中含有 football 和 basketball 任意一個,就可以被匹配到。
如果將 operator 操作符的值改為 and ,則表示需要同時包含 football 和 basketball , 得到的結(jié)果就只能是 文檔 1 Jim 小朋友了。
analyzeranalyzer 屬性是指在對查詢文本分析時的分析器
如果沒有指定則會使用字段mapping 時指定的分析器
如果字段在 mapping 時也沒有明顯指定,則會使用默認的 search analyzer。
這里我們也沒有指定,就會使用默認的,就不舉例了,在后面文章講解 analyzer 時再拓展。
lenient 參數(shù)默認值是 false , 表示用來在查詢時如果數(shù)據(jù)類型不匹配且無法轉(zhuǎn)換時會報錯。如果設置成 true 會忽略錯誤。
例如, 例子中的 age 是 integer 類型的,如果查詢 age=xxy ,就會導致無法轉(zhuǎn)換而報錯。
GET matchtest/_search { "query": { "match": { "age" : { "query": "xxx" } } } }
而如果將 lenient 參數(shù)設置為 true ,就會忽略這個錯誤
GET matchtest/_search { "query": { "match": { "age" : { "query": "xxx", "lenient": true } } } }
注意,如果將 age 字段的值設置為字符串 "10", 來查詢,由于能夠轉(zhuǎn)換成整數(shù),這時 elastic 內(nèi)部會將 字符串先轉(zhuǎn)換成整數(shù)再做查詢,不會報錯。
Fuzziness fuzzniess 參數(shù)fuzziness 參數(shù)可以是查詢的字段具有模糊搜索的特性。來先了解下什么是模糊搜索。
什么是模糊搜索?模糊搜索是指系統(tǒng)允許被搜索信息和搜索提問之間存在一定的差異,這種差異就是“模糊”在搜索中的含義。例如,查找名字Smith時,就會找出與之相似的Smithe, Smythe, Smyth, Smitt等。——百度百科
通過模糊搜索可以查詢出存在一定相似度的單詞,那么怎么計算兩個單詞是否有相似度以及相似度的大小呢?這就要了解下另外一個概念:Levenshtein Edit Distance
Levenshtein Edit DistanceLevenshtein Edit Distance 叫做萊文斯坦距離**,是編輯距離的一種。指兩個字串之間,由一個轉(zhuǎn)成另一個所需的最少編輯操作次數(shù)。允許的編輯操作包括將一個字符替換成另一個字符,插入一個字符,刪除一個字符。
例如,單詞 "god" 只需要插入一個 "o" 字符就可以變?yōu)? "good",因此它們之間的編輯距離為 1。
fuzziness 參數(shù)取值規(guī)則了解了上面兩個概念,回過頭再來看下 fuzziness 參數(shù)。
在查詢 text 或者 keyword 類型的字段時, fuzziness 可以看做是萊文斯坦距離。
fuzziness 參數(shù)的取值如下
0,1,2 表示最大可允許的萊文斯坦距離
AUTO
會根據(jù)詞項的長度來產(chǎn)生可編輯距離,它還有兩個可選參數(shù),形式為AUTO:[low],[high], 分別表示短距離參數(shù)和長距離參數(shù);如果沒有指定,默認值是 AUTO:3,6 表示的意義如下
0..2
單詞長度為 0 到 2 之間時必須要精確匹配,這其實很好理解,單詞長度太短是沒有相似度可言的,例如 "a" 和 "b"。
3..5
單詞長度 3 到 5 個字母時,最大編輯距離為 1
>5
單詞長度大于 5 個字母時,最大編輯距離為 2
最佳實踐: fuzziness 在絕大多數(shù)場合都應該設置成 AUTO
如果不設置 fuziness 參數(shù),查詢是精確匹配的。
來看例子,上面創(chuàng)建了一個 doc
PUT matchtest/people/1 { "name" : "Jim", "age": 10, "hobbies": "football, basketball, pingpang" }
設置 fuzziness 為 AUTO ,
其中 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 表示不能沒模糊化的初始字符數(shù)。由于大部分的拼寫錯誤發(fā)生在詞的結(jié)尾,而不是詞的開始,使用 prefix_length 就可以完成優(yōu)化。注意 prefix_length 必須結(jié)合 fuzziness 參數(shù)使用。
例如,在查詢 hobbies 中的 football 時,將 prefix_length 參數(shù)設置為 3,這時 foatball 將不能被匹配。
GET matchtest/_search { "query": { "match": { "hobbies": { "query": "foatball", "fuzziness": "AUTO", "prefix_length": 3 } } } }
TODO(max_expansions 參數(shù)對于 match 查詢而言,沒理解表示的意義,如果您知道這個參數(shù)的用法,請給我留言告知,不勝感謝! )
Zero terms Query先看例子, 先創(chuàng)建一個文檔 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)就屬于高頻詞,它雖然出現(xiàn)頻率較高,但在匹配時可能并不太相關。實際上,我們往往是想要文檔能盡可能的匹配那些低頻詞,也就是更重要的詞項。
要實現(xiàn)這個需求,只要在查詢時配置 cutoff_frequency 參數(shù)就可以了。假設我們將 cutoff_frequency 設置成 0.01 就表示
任何詞項在文檔中超過 1%, 被認為是高頻詞
其他的詞項會被認為低頻詞
從而將高頻詞(次重要的詞)挪到可選子查詢中,讓它們只參與評分,而不參與匹配;高頻詞(更重要的詞)參與匹配和評分。
這樣一來,就不再需要 stopwords 停用詞文件了,從而變成了動態(tài)生成停用詞: 高頻詞就會被看做是停用詞。這種配置只是對于詞項比較多的場合如 email body,文章等適用,文字太少, cutoff_frequency 選項設置的意義就不大了。
cutoff_frequency 配置有兩種形式
指定為一個分數(shù)( 0.01 )表示出現(xiàn)頻率
指定為一個正整數(shù)( 5 )則表示出現(xiàn)次數(shù)
下面給個例子, 在創(chuàng)建的 3 個文檔中都包含 "be " 的單詞,在查詢時將 cutoff_frequency 參數(shù)設置為 2, 表示 "be" 就是高頻詞,只會參與評分,但在匹配時不做考慮。
此時查詢的內(nèi)容為 "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 查詢是支持多詞條的同義詞擴展的。在應用過濾器后,解析器會對每個多次條同義詞創(chuàng)建一個語句查詢。
例如,同義詞 USA, united states of America 就會構(gòu)建出 (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" } } } }小結(jié)
本文以代碼實例的方式完整的講解了 Match Query 的各種使用場景和參數(shù)意義。下篇會講解 Match Phrase Query 敬請期待。
參考文檔[Elasticsearch Query DSL Match Query] (https://www.elastic.co/guide/...
傳送門reycg-blog
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/72334.html
摘要:如果遇到非常的復雜的匹配,正則表達式的優(yōu)勢就更加明顯了。關于正則表達式書寫規(guī)則,可查看,上面說的很清楚了,我就不貼出來了。替換與正則表達式匹配的子串,并返回替換后的字符串。結(jié)語正則表達式并不難,懂了其中的套路之后,一切都變得簡單了。 前言 在正文開始前,先說說正則表達式是什么,為什么要用正則表達式?正則表達式在我個人看來就是一個瀏覽器可以識別的規(guī)則,有了這個規(guī)則,瀏覽器就可以幫我們判斷...
摘要:所以查閱官方文檔以及他人造好的輪子,總結(jié)了一些面試和學習中你必須掌握的問題。在微博應用中,可以將一個用戶所有的關注人存在一個集合中,將其所有粉絲存在一個集合。 昨天寫了一篇自己搭建redis集群并在自己項目中使用的文章,今天早上看別人寫的面經(jīng)發(fā)現(xiàn)redis在面試中還是比較常問的(筆主主Java方向)。所以查閱官方文檔以及他人造好的輪子,總結(jié)了一些redis面試和學習中你必須掌握的問題。...
摘要:注解在類上為類提供一個全參的構(gòu)造方法,加了這個注解后,類中不提供默認構(gòu)造方法了。這個注解用在類上,使用類中所有帶有注解的或者帶有修飾的成員變量生成對應的構(gòu)造方法。 轉(zhuǎn)載請注明原創(chuàng)地址:http://www.54tianzhisheng.cn/2018/01/07/lombok/ showImg(http://ohfk1r827.bkt.clouddn.com/blog/180107/7...
閱讀 3207·2021-11-10 11:36
閱讀 3153·2021-11-02 14:39
閱讀 1732·2021-09-26 10:11
閱讀 4963·2021-09-22 15:57
閱讀 1692·2021-09-09 11:36
閱讀 2055·2019-08-30 12:56
閱讀 3493·2019-08-30 11:17
閱讀 1707·2019-08-29 17:17