關(guān)于elasticsearch的match_phrase_prefix查詢(xún)?cè)斀?/h1>
更新時(shí)間:2023年03月21日 10:09:28 作者:自東向西
這篇文章主要介紹了關(guān)于elasticsearch的match_phrase_prefix查詢(xún)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
match_phrase
match_phrase_prefix可以認(rèn)為是match_phrase的增強(qiáng)版本,所以先了解一下match_phrase。
match_phrase詞組匹配會(huì)先解析檢索詞,并且標(biāo)注出每個(gè)的token相對(duì)位置,搜索匹配的字段的必須包含所有的檢索詞的token,并且他們的相對(duì)位置也要和檢索詞里面相同。
在《系統(tǒng)學(xué)習(xí)ElasticSearch》中,有很好的例子:
# DSL語(yǔ)句
GET /tehero_index/_doc/_search
{
"query":{
"match_phrase":{
"content.ik_smart_analyzer":"系統(tǒng)編程"
}
}
DSL執(zhí)行步驟分析:
1)檢索詞“系統(tǒng)編程”被分詞為兩個(gè)Token【系統(tǒng),Position=0】【編程,Position=1】;
2)倒排索引檢索時(shí),等價(jià)于sql:【where Token = 系統(tǒng) and 系統(tǒng)_Position=0 and Token = 編程 and 編程_Position=1】;
如果我們不要求這兩個(gè)單詞相鄰,希望放松一點(diǎn)條件,可以添加slop參數(shù),slop代表兩個(gè)token之間相隔的最多的距離(最多需要移動(dòng)多少次才能相鄰)。
match_phrase_prefix
與match_phrase查詢(xún)類(lèi)似,但是會(huì)對(duì)最后一個(gè)Token在倒排序索引列表中進(jìn)行通配符搜索。
# DSL語(yǔ)句
GET /tehero_index/_doc/_search
{
"query":{
"match_phrase":{
"content.ik_smart_analyzer":"我編程系"
}
}
這個(gè)分詞的結(jié)果會(huì)是“我”、“編程”、“系”。
“我”和“編程”是精確匹配,“系”是前綴匹配,等價(jià)于sql:【where Token = ‘我’ and 我_Position=0 and Token = ‘編程’ and 編程_Position=1 and (Token_Position=2 and Token like ‘系%’)】
需要注意的點(diǎn)
elasticsearch的官網(wǎng)文檔上,有match_phrase_prefix的完整參數(shù)結(jié)構(gòu):

query
,查詢(xún)的關(guān)鍵字analyer
,對(duì)關(guān)鍵字使用的分詞器max_expansions
,最后一個(gè)term做前綴匹配時(shí)的最大拓展數(shù),默認(rèn)是50slop
,與match_phrase
的slop相同,允許term之間的最大間隔zero_terms_query
,經(jīng)過(guò)analyer解析后,沒(méi)有任何term時(shí),不返回?cái)?shù)據(jù),還是返回全部數(shù)據(jù)。默認(rèn)返回全部數(shù)據(jù)。
max_expansions是非常重要的一個(gè)參數(shù),需要留意下,不然很容易出現(xiàn)與我們期望不符合的情況。
- 在工作中,我試過(guò)使用match_phrase_prefix來(lái)匹配手機(jī)號(hào),但是出現(xiàn)了一些奇怪的現(xiàn)象:
- 測(cè)試的手機(jī)號(hào)是“123454688885555”,使用match_phrase_prefix,關(guān)鍵字是“12345”來(lái)查詢(xún)指定租戶(hù)下的數(shù)據(jù),沒(méi)有返回任何文檔。把關(guān)鍵字換成“1234546”,正確返回了對(duì)應(yīng)的文檔。
為什么會(huì)這樣呢?為什么12345就不返回,1234546就返回了?
個(gè)人是這樣覺(jué)得的:
- 手機(jī)號(hào)雖然存在es中是字符串,但是字符串的內(nèi)容是數(shù)字,分詞器并不會(huì)對(duì)它進(jìn)行分詞,也就是一個(gè)手機(jī)號(hào)就是一個(gè)term
- 在測(cè)試數(shù)據(jù)中,數(shù)據(jù)有5000條,每條數(shù)據(jù)的手機(jī)號(hào)碼都是不一樣的,也就是說(shuō),手機(jī)號(hào)這樣的term有5000個(gè)。
- max_expansions默認(rèn)是50,也就是說(shuō),會(huì)把12345拓展出以12345為開(kāi)頭的額外50個(gè)term,例如123456、1234546、123456898…
- 最后將拓展出來(lái)的term也用于查詢(xún)
為什么我會(huì)認(rèn)為是這樣的過(guò)程呢?
elasticsearch除了會(huì)構(gòu)建倒排索引之外,還會(huì)在所有的term構(gòu)建一個(gè)term dictionary (詞典)和term index(詞索引,印象是跳躍表結(jié)構(gòu)),幫助查找。
當(dāng)出現(xiàn)前綴匹配的時(shí)候,可以在term index和term dictionary中快速找到對(duì)應(yīng)開(kāi)通的term。
根據(jù)max_expansions的值,拿到指定個(gè)數(shù)的term。
12345查不到數(shù)據(jù),1234546能查找,明顯是1234546更精確,1234546拓展出來(lái)的term中包含了那個(gè)完整的手機(jī)號(hào)碼123454688885555。
在查詢(xún)這個(gè)參數(shù)相關(guān)的文章的時(shí)候,發(fā)現(xiàn):
- 有的人認(rèn)為這個(gè)數(shù)值是值通配符,值是50,就能模糊匹配多關(guān)鍵字之后50的字符的term。有的人認(rèn)為這個(gè)數(shù)值是匹配的文檔數(shù),值是50,則匹配50個(gè)文檔,返回這50個(gè)文檔中命中的部分。
- 這都是不對(duì)的,明顯與手機(jī)號(hào)的實(shí)驗(yàn)不符。
- 《系統(tǒng)學(xué)習(xí)ElasticSearch》中對(duì)max_expansions的描述就像是占位符…
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
-
Java使用DFA算法實(shí)現(xiàn)敏感詞過(guò)濾的示例代碼
很多項(xiàng)目中都會(huì)有一個(gè)敏感詞管理模塊,本文主要介紹了Java使用DFA算法實(shí)現(xiàn)敏感詞過(guò)濾的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧 2023-03-03
-
SpringCloud之Feign遠(yuǎn)程接口映射的實(shí)現(xiàn)
這篇文章主要介紹了SpringCloud之Feign遠(yuǎn)程接口映射的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧 2020-09-09
-
java通過(guò)DelayQueue實(shí)現(xiàn)延時(shí)任務(wù)
本文主要介紹了java通過(guò)DelayQueue實(shí)現(xiàn)延時(shí)任務(wù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧 2023-07-07
-
java中HashMap.values()轉(zhuǎn)為ArrayList()問(wèn)題
這篇文章主要介紹了java中HashMap.values()轉(zhuǎn)為ArrayList()問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教 2023-03-03
-
Java實(shí)現(xiàn)求數(shù)組最長(zhǎng)子序列算法示例
這篇文章主要介紹了Java實(shí)現(xiàn)求數(shù)組最長(zhǎng)子序列算法,涉及java針對(duì)數(shù)組的遞歸遍歷、判斷相關(guān)操作技巧,需要的朋友可以參考下 2018-07-07
最新評(píng)論
match_phrase
match_phrase_prefix可以認(rèn)為是match_phrase的增強(qiáng)版本,所以先了解一下match_phrase。
match_phrase詞組匹配會(huì)先解析檢索詞,并且標(biāo)注出每個(gè)的token相對(duì)位置,搜索匹配的字段的必須包含所有的檢索詞的token,并且他們的相對(duì)位置也要和檢索詞里面相同。
在《系統(tǒng)學(xué)習(xí)ElasticSearch》中,有很好的例子:
# DSL語(yǔ)句 GET /tehero_index/_doc/_search { "query":{ "match_phrase":{ "content.ik_smart_analyzer":"系統(tǒng)編程" } }
DSL執(zhí)行步驟分析:
1)檢索詞“系統(tǒng)編程”被分詞為兩個(gè)Token【系統(tǒng),Position=0】【編程,Position=1】;
2)倒排索引檢索時(shí),等價(jià)于sql:【where Token = 系統(tǒng) and 系統(tǒng)_Position=0 and Token = 編程 and 編程_Position=1】;
如果我們不要求這兩個(gè)單詞相鄰,希望放松一點(diǎn)條件,可以添加slop參數(shù),slop代表兩個(gè)token之間相隔的最多的距離(最多需要移動(dòng)多少次才能相鄰)。
match_phrase_prefix
與match_phrase查詢(xún)類(lèi)似,但是會(huì)對(duì)最后一個(gè)Token在倒排序索引列表中進(jìn)行通配符搜索。
# DSL語(yǔ)句 GET /tehero_index/_doc/_search { "query":{ "match_phrase":{ "content.ik_smart_analyzer":"我編程系" } }
這個(gè)分詞的結(jié)果會(huì)是“我”、“編程”、“系”。
“我”和“編程”是精確匹配,“系”是前綴匹配,等價(jià)于sql:【where Token = ‘我’ and 我_Position=0 and Token = ‘編程’ and 編程_Position=1 and (Token_Position=2 and Token like ‘系%’)】
需要注意的點(diǎn)
elasticsearch的官網(wǎng)文檔上,有match_phrase_prefix的完整參數(shù)結(jié)構(gòu):
query
,查詢(xún)的關(guān)鍵字analyer
,對(duì)關(guān)鍵字使用的分詞器max_expansions
,最后一個(gè)term做前綴匹配時(shí)的最大拓展數(shù),默認(rèn)是50slop
,與match_phrase
的slop相同,允許term之間的最大間隔zero_terms_query
,經(jīng)過(guò)analyer解析后,沒(méi)有任何term時(shí),不返回?cái)?shù)據(jù),還是返回全部數(shù)據(jù)。默認(rèn)返回全部數(shù)據(jù)。
max_expansions是非常重要的一個(gè)參數(shù),需要留意下,不然很容易出現(xiàn)與我們期望不符合的情況。
- 在工作中,我試過(guò)使用match_phrase_prefix來(lái)匹配手機(jī)號(hào),但是出現(xiàn)了一些奇怪的現(xiàn)象:
- 測(cè)試的手機(jī)號(hào)是“123454688885555”,使用match_phrase_prefix,關(guān)鍵字是“12345”來(lái)查詢(xún)指定租戶(hù)下的數(shù)據(jù),沒(méi)有返回任何文檔。把關(guān)鍵字換成“1234546”,正確返回了對(duì)應(yīng)的文檔。
為什么會(huì)這樣呢?為什么12345就不返回,1234546就返回了?
個(gè)人是這樣覺(jué)得的:
- 手機(jī)號(hào)雖然存在es中是字符串,但是字符串的內(nèi)容是數(shù)字,分詞器并不會(huì)對(duì)它進(jìn)行分詞,也就是一個(gè)手機(jī)號(hào)就是一個(gè)term
- 在測(cè)試數(shù)據(jù)中,數(shù)據(jù)有5000條,每條數(shù)據(jù)的手機(jī)號(hào)碼都是不一樣的,也就是說(shuō),手機(jī)號(hào)這樣的term有5000個(gè)。
- max_expansions默認(rèn)是50,也就是說(shuō),會(huì)把12345拓展出以12345為開(kāi)頭的額外50個(gè)term,例如123456、1234546、123456898…
- 最后將拓展出來(lái)的term也用于查詢(xún)
為什么我會(huì)認(rèn)為是這樣的過(guò)程呢?
elasticsearch除了會(huì)構(gòu)建倒排索引之外,還會(huì)在所有的term構(gòu)建一個(gè)term dictionary (詞典)和term index(詞索引,印象是跳躍表結(jié)構(gòu)),幫助查找。
當(dāng)出現(xiàn)前綴匹配的時(shí)候,可以在term index和term dictionary中快速找到對(duì)應(yīng)開(kāi)通的term。
根據(jù)max_expansions的值,拿到指定個(gè)數(shù)的term。
12345查不到數(shù)據(jù),1234546能查找,明顯是1234546更精確,1234546拓展出來(lái)的term中包含了那個(gè)完整的手機(jī)號(hào)碼123454688885555。
在查詢(xún)這個(gè)參數(shù)相關(guān)的文章的時(shí)候,發(fā)現(xiàn):
- 有的人認(rèn)為這個(gè)數(shù)值是值通配符,值是50,就能模糊匹配多關(guān)鍵字之后50的字符的term。有的人認(rèn)為這個(gè)數(shù)值是匹配的文檔數(shù),值是50,則匹配50個(gè)文檔,返回這50個(gè)文檔中命中的部分。
- 這都是不對(duì)的,明顯與手機(jī)號(hào)的實(shí)驗(yàn)不符。
- 《系統(tǒng)學(xué)習(xí)ElasticSearch》中對(duì)max_expansions的描述就像是占位符…
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java使用DFA算法實(shí)現(xiàn)敏感詞過(guò)濾的示例代碼
很多項(xiàng)目中都會(huì)有一個(gè)敏感詞管理模塊,本文主要介紹了Java使用DFA算法實(shí)現(xiàn)敏感詞過(guò)濾的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03SpringCloud之Feign遠(yuǎn)程接口映射的實(shí)現(xiàn)
這篇文章主要介紹了SpringCloud之Feign遠(yuǎn)程接口映射的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09java通過(guò)DelayQueue實(shí)現(xiàn)延時(shí)任務(wù)
本文主要介紹了java通過(guò)DelayQueue實(shí)現(xiàn)延時(shí)任務(wù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07java中HashMap.values()轉(zhuǎn)為ArrayList()問(wèn)題
這篇文章主要介紹了java中HashMap.values()轉(zhuǎn)為ArrayList()問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03Java實(shí)現(xiàn)求數(shù)組最長(zhǎng)子序列算法示例
這篇文章主要介紹了Java實(shí)現(xiàn)求數(shù)組最長(zhǎng)子序列算法,涉及java針對(duì)數(shù)組的遞歸遍歷、判斷相關(guān)操作技巧,需要的朋友可以參考下2018-07-07