Elasticsearch模糊查詢
前綴查詢?cè)?/h2>
不計(jì)算相關(guān)度評(píng)分
前綴搜索匹配的是term,而不是field。即搜索倒排索引
前綴搜索的性能很差
前綴搜索沒有緩存
前綴搜索盡可能把前綴長(zhǎng)度設(shè)置的更長(zhǎng)命中索引越少,性能會(huì)好
要注意分詞器,如果分詞器分詞了會(huì)導(dǎo)致前綴匹配失敗.尤其是中文要設(shè)置中文分詞器
前綴索引示例
// 創(chuàng)建prefix索引; 索引最大最小長(zhǎng)度
//含義:對(duì)詞項(xiàng)繼續(xù)創(chuàng)建倒排索引. 指的是比如一個(gè)詞Elasticsearch, el建一個(gè)倒排索引,ela再建一個(gè),根據(jù)你的min和max; 索引的基礎(chǔ)上繼續(xù)創(chuàng)建索引,浪費(fèi)空間,提高性能;
前綴索引要注意分詞;
##沒有分詞的前綴索引查詢
POST /my_index1/_bulk?filter_path=items.*.error
{"index":{"_id":"1"}}
{"text":"城管打電話喊商販去擺攤攤"}
{"index":{"_id":"2"}}
{"text":"笑果文化回應(yīng)商販老農(nóng)去擺攤"}
{"index":{"_id":"3"}}
{"text":"老農(nóng)耗時(shí)17年種出椅子樹"}
{"index":{"_id":"4"}}
{"text":"夫妻結(jié)婚30多年AA制,被城管抓"}
{"index":{"_id":"5"}}
{"text":"黑人見義勇為阻止搶劫反被銬住"}
GET my_index1/_search
{
"query": {
"prefix": {
"text": {
"value": "城管"
}
}
}
}
##有中文分詞的前綴索引
##filter_path=items.*.error 這個(gè)表示只顯示錯(cuò)誤信息
##設(shè)置mapping 先把mapping模板查出來
DELETE my_index2
GET my_index2/_mapping
PUT my_index2
{
"mappings": {
"properties": {
"text": {
"type": "text",
"analyzer": "ik_max_word",
// 創(chuàng)建prefix索引; 索引最大最小長(zhǎng)度
//含義:對(duì)詞項(xiàng)繼續(xù)創(chuàng)建倒排索引. 指的是比如一個(gè)詞Elasticsearch, el建一個(gè)倒排索引,ela再建一個(gè),根據(jù)你的min和max; 索引的基礎(chǔ)上繼續(xù)創(chuàng)建索引,浪費(fèi)空間,提高性能;
"index_prefixes": {
"min_chars":2,
"max_chars":4
},
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
POST /my_index2/_bulk?filter_path=items.*.error
{"index":{"_id":"1"}}
{"text":"城管打電話喊商販去擺攤攤"}
{"index":{"_id":"2"}}
{"text":"笑果文化回應(yīng)商販老農(nóng)去擺攤"}
{"index":{"_id":"3"}}
{"text":"老農(nóng)耗時(shí)17年種出椅子樹"}
{"index":{"_id":"4"}}
{"text":"夫妻結(jié)婚30多年AA制,被城管抓"}
{"index":{"_id":"5"}}
{"text":"黑人見義勇為阻止搶劫反被銬住"}
GET my_index2/_search
GET my_index2/_search
{
"query": {
"prefix": {
"text": {
"value": "城管"
}
}
}
}
通配符 willward
通配符也匹配的是term
##英文通配符數(shù)據(jù)
POST /product_en/_bulk?filter_path=iterm.*.error
{"index":{"_id":"1"}}
{"title":"my english","desc":"shouji zhong de zhandouji","price":3999,"tags":["xingjiabi","fashao","buka","1"]}
{"index":{"_id":"2"}}
{"title":"xiaomi nfc phone","desc":"zhichi quangongneng nfc,shouji zhong de jianjiji","price":4999,"tags":["xingjiabi","fashao","gongjiaoka","asd2fgas"]}
{"index":{"_id":"3"}}
{"title":"nfc phone","desc":"shouji zhong de hongzhaji","price":2999,"tags":["xingjiabi","fashao","menjinka","as345"]}
{"title":{"_id":"4"}}
{"text":"xiaomi erji","desc":"erji zhong de huangmenji","price":999,"tags":["low","bufangshui","yinzhicha","4dsg"]}
{"index":{"_id":"5"}}
{"title":"hongmi erji","desc":"erji zhong de kendeji","price":399,"tags":["lowbee","xuhangduan","zhiliangx","sdg5"]}
GET product_en/_search
{
"query": {
"wildcard": {
// 加keyword和不加是有區(qū)別
"title.keyword": {
"value": "nfc*"
}
}
}
}
上邊代碼加keyword和不加是有區(qū)別的, keyword是不會(huì)分詞的,field是會(huì)分詞的
正則
flags
指的是允許使用正則表達(dá)式中哪些通配符
ALL
啟用所有可選操作符。
COMPLEMENT
啟用操作符。可以使用對(duì)下面最短的模式進(jìn)行否定。例如
a~bc # matches 'adc' and 'aec' but not 'abc'
INTERVAL
啟用<>操作符??梢允褂?lt;>匹配數(shù)值范圍。例如
foo<1-100> # matches 'foo1', 'foo2' ... 'foo99', 'foo100'
foo<01-100> # matches 'foo01', 'foo02' ... 'foo99', 'foo100'
INTERSECTION
啟用&操作符,它充當(dāng)AND操作符。如果左邊和右邊的模式都匹配,則匹配成功。例如:
aaa.+&.+bbb # matches 'aaabbb'
ANYSTRING
啟用@操作符。您可以使用@來匹配任何整個(gè)字符串。
您可以將@操作符與&和~操作符組合起來,創(chuàng)建一個(gè)“everything except”邏輯。例如:
@&~(abc.+) # matches everything except terms beginning with 'abc'
模糊查詢
主要是解決你輸入錯(cuò)誤能智能糾錯(cuò)的功能,本質(zhì)也是模糊查詢
常見的如:
缺少字符/多字符/混淆字符(輸入錯(cuò)了)/順序顛倒
語法
GET <index>/_search
{
"query": {
"fuzzy": {
"<field>": {
"value": "<keyword>"
}
}
}
}
value必輸項(xiàng)
數(shù)據(jù)實(shí)測(cè)
比如你有如下數(shù)據(jù):
"hits" : [
{
"_index" : "product_en",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.8829135,
"_source" : {
"title" : "xiaomi nfc phone",
"desc" : "zhichi quangongneng nfc,shouji zhong de jianjiji",
"price" : 4999,
"tags" : [
"xingjiabi",
"fashao",
"gongjiaoka",
"asd2fgas"
]
}
}
]
以下查詢 都可以查出數(shù)據(jù)
GET product_en/_search
{
"query": {
"fuzzy": {
"title": {
// "value": "xiaoi"
// "value": "mixiao"
// "ixaomi"
"value": "xiaohi"
}
}
}
}
召回率優(yōu)化
根據(jù)以上原理我們知道, 輸入錯(cuò)誤的數(shù)量是有限制的. 那么哪里限制的? 怎么修改? 設(shè)置多少合適呢
我們輸入錯(cuò)幾個(gè)字符可以匹配呢?
把錯(cuò)誤的字符修正成正確需要的步驟數(shù)量,稱為編輯距離. 這距離計(jì)算跟特定的計(jì)算公式有關(guān)系:
兩段文本之間的Damerau-Levenshtein距離是使一個(gè)字符串與另一個(gè)字符串匹配所需的插入、刪除、替換和調(diào)換的數(shù)量
距離公式:lucene使用Levenshtein算法,es使用改進(jìn)版Damerau-Levenshtein,
如axe=>aex不同算法需要步驟: Levenshtein=2 Damerau-Levenshtein=1
這個(gè)距離越大允許錯(cuò)的字符就越多.
但是這個(gè)距離并非越大越好,越大召回率越高,但是召回率高不代表準(zhǔn)確,也許更不準(zhǔn)確了.
ES默認(rèn)的編輯距離編輯距離,(0,1,2)
模糊查詢的幾個(gè)參數(shù)
value: 必須,關(guān)鍵詞
fuzziness: 可選,定義編輯距離,es默認(rèn)(0,1,2);可以設(shè)置"AUTO",es會(huì)根據(jù)字符串長(zhǎng)度動(dòng)態(tài)的取值.
transpositions:(可選,布爾值)指示編輯是否包括兩個(gè)相鄰字符的變位(ab→ba)。默認(rèn)為true。影響某些編輯距離的計(jì)算結(jié)果.true的話是改進(jìn)版對(duì)換距離為1,如果false就變?yōu)?了.
GET product_en/_search
{
"query": {
"fuzzy": {
"title": {
"value": "ixaomi",
//"fuzziness": "AUTO"
"fuzziness": 5
}
}
}
}
match_phase
性能差
基本要求
- match phase會(huì)被分詞
- 匹配要求: 搜索詞和源數(shù)據(jù)的分詞順序一致; 中間不能又其他詞
匹配原理
允許搜索詞最后一個(gè)詞項(xiàng)作為前綴再次檢索
匹配流程:
最后一個(gè)詞項(xiàng)作為前綴,匹配所有詞->再使用搜索詞剩余前綴再次前綴匹配
整個(gè)過程比較耗費(fèi)性能的.
示例
abc cde fg
比如用這個(gè)詞作為短語匹配的搜索詞,它首先找以fg
開頭的滿足的所有詞項(xiàng),在這些詞項(xiàng)中再去匹配abc cde
開頭的.
match_phrase_prefix與match_phrase
match_phrase_prefix與match_phrase相同,但是它多了一個(gè)特性,就是它允許在文本的最后一個(gè)詞項(xiàng)(term)上的前綴匹配,
如果是一個(gè)單詞,比如a,它會(huì)匹配文檔字段所有以a開頭的文檔;
如果是一個(gè)短語,比如 “it is horse” ,他會(huì)先在倒排索引中做以horse做前綴搜索,然后在匹配到的doc中做match_phrase查詢
性能調(diào)優(yōu)
如何避免匹配詞過多呢?
可以使用max_expentions
.這個(gè)參數(shù)默認(rèn)值是50
這里尤其要注意max_expentions=1時(shí)并不代表實(shí)際返回結(jié)果就是1個(gè). 這里的1每個(gè)分片限制的數(shù)量, 如果有多個(gè)分片的話每個(gè)分片都可能匹配到一個(gè)(如果匹配不到就沒辦法了)
詞序顛倒召回率調(diào)優(yōu)
使用參數(shù)slop
測(cè)試腳本
GET product_en/_search
{
"query": {
"match_phrase": {
"desc": "shouji zhong de"
}
}
}
GET product_en/_search
##test expansions
##驗(yàn)證雖然max_expansions=1但是依然返回了多個(gè)結(jié)果
GET product_en/_search
{
"query": {
"match_phrase_prefix": {
"desc": {
"query": "shouji zhong",
"max_expansions": 1
}
}
}
}
##test slop
##
GET product_en/_search
{
"query": {
"match_phrase_prefix": {
"desc": {
//源數(shù)據(jù)"shouji zhong de hongzhaji",搜索詞:"shouji hongzhaji"時(shí)slop=2是可以的slop=1就不行了
//除了上面間隔詞項(xiàng),順序顛倒也可以的,搜索詞:"de zhong hongzhaji"
"query": "de zhong shouji hongzhaji",
"max_expansions": 50
,"slop": 5
}
}
}
}
ngram & edge-ngram
可以用作切詞方式
ngram是按照字符進(jìn)行切詞
根據(jù)如下代碼查看效果:
GET _analyze
{
"tokenizer": "ngram",
"text": ["abc def opq"]
}
具體怎么切詞可以通過min_gram max_gram來控制
作為過濾器
##也可以過濾器
GET _analyze
{
"tokenizer": "standard",
"filter": ["ngram"],
"text": ["abc def opq"]
}
一個(gè)分析器包含
- 字符過濾器(Character Filters):用于在分詞之前對(duì)原始文本進(jìn)行預(yù)處理,如HTML標(biāo)簽的去除、字符替換等。
- 分詞器(Tokenizer):將原始文本按照一定的規(guī)則進(jìn)行切分,生成詞條(Terms)。常見的分詞器有標(biāo)準(zhǔn)分詞器(Standard Tokenizer)、簡(jiǎn)單分詞器(Simple Tokenizer)、正則表達(dá)式分詞器(Pattern Tokenizer)等。
- 詞條過濾器(Token Filters):對(duì)切分后的詞條進(jìn)行進(jìn)一步處理,如小寫轉(zhuǎn)換、去除停用詞、詞干提取等。
- 字符映射過濾器(Character Mapping Filter):用于字符的映射轉(zhuǎn)換,如大小寫轉(zhuǎn)換、字符替換等。
ngram代碼測(cè)試
##test data
POST /test_idx_001/_bulk
{ "index": { "_id": "1"} }
{ "text": "my english" }
{ "index": { "_id": "2"} }
{ "text": "my english is good" }
{ "index": { "_id": "3"} }
{ "text": "my chinese is good" }
{ "index": { "_id": "4"} }
{ "text": "my japanese is nice" }
{ "index": { "_id": "5"} }
{ "text": "my disk is full" }
DELETE test_idx_001
PUT test_idx_001
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer":{
"type": "custom",
"tokenizer":"standard",
"filter": "my_filter_ngram"
}
},
"tokenizer": {},
"filter": {
"my_filter_ngram":{
"type": "ngram",
"min_gram":2,
"max_gram":3
}
},
"char_filter": {}
}
},
"mappings": {
"properties": {
"myproperties":{
"type": "text",
"analyzer": "my_analyzer",
"search_analyzer": "standard"
}
}
}
}
測(cè)試ngram個(gè)數(shù)
##test data
POST /test_idx_001/_bulk
{ "index": { "_id": "1"} }
{ "text": "my english" }
{ "index": { "_id": "2"} }
{ "text": "my english is good" }
{ "index": { "_id": "3"} }
{ "text": "my chinese is good" }
{ "index": { "_id": "4"} }
{ "text": "my japanese is nice" }
{ "index": { "_id": "5"} }
{ "text": "my disk is full" }
DELETE test_idx_001
PUT test_idx_001
{
"settings": {
"analysis": {
"filter": {
"my_filter_ngram": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 3
}
},
"analyzer": {
"my_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": "my_filter_ngram"
}
}
}
},
"mappings": {
"properties": {
"text": {
"type": "text",
"analyzer": "my_analyzer",
"search_analyzer": "standard"
}
}
}
}
GET test_idx_001/_search
GET test_idx_001/_search
{
"query": {
"match_phrase": {
//這里的每個(gè)詞項(xiàng)必須在2,3范圍內(nèi)因?yàn)榉衷~就是按照這個(gè)數(shù)量分詞的,這數(shù)量是在上面定義的
//比如你輸入engl就查不到數(shù)據(jù)了
"text": "my eng is goo"
}
}
}
ngram如果設(shè)置的過小會(huì)占用大量的磁盤空間,因?yàn)樗鼤?huì)創(chuàng)建很多倒排索引
edge-ngram測(cè)試
edge-ngram會(huì)節(jié)省空間
edge與ngram的區(qū)別在于它只對(duì)前N個(gè)字母生成索引.具體:
比如my english
我們?cè)O(shè)置min_gram=2;max_gram=3; 它只會(huì)對(duì)my eng進(jìn)行索引;
ngram會(huì)對(duì)my, my空格, 空格e, 空格en, eng,…等等依次做索引文章來源:http://www.zghlxwxcb.cn/news/detail-533098.html
即ngram不僅前綴,還可以中綴搜索文章來源地址http://www.zghlxwxcb.cn/news/detail-533098.html
DELETE test_idx_001
PUT test_idx_001
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer":{
"type": "custom",
"tokenizer": "standard",
"filter": "myfitler"
}
},
"filter": {
"myfitler":{
"type":"edge_ngram",
"min_gram": 2,
"max_gram": 3
}
},
"tokenizer": {}
}
},
"mappings": {
"properties": {
"text":{
"type": "text",
"analyzer": "my_analyzer",
"search_analyzer": "standard"
}
}
}
}
GET test_idx_001/_search
{
"query": {
"match_phrase": {
"text": "my eng"
}
}
}
到了這里,關(guān)于Elasticsearch模糊查詢的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!