设置Elasticsearch N-Gram字分析器的过程
說(shuō)n-gram是一個(gè)大話題,這是輕描淡寫(xiě)的。 進(jìn)行快速搜索,您會(huì)發(fā)現(xiàn)自己盯著語(yǔ)言學(xué)和語(yǔ)言模型,數(shù)據(jù)挖掘或特定蛋白質(zhì)的分解對(duì)首次亮相文化的衰落所隱含的信息量。
好吧,我在跟那最后一個(gè)開(kāi)玩笑。 但是,如果您是開(kāi)發(fā)人員,希望使用Elasticsearch在應(yīng)用程序中進(jìn)行搜索,那么您很有可能需要以實(shí)用的方式使用n-gram分析器來(lái)進(jìn)行某些搜索,并且可能需要一些針對(duì)性的信息才能獲得您的搜索以期望的方式表現(xiàn)。 在Elasticsearch中使用n-gram搜索可以做的事情有很多可能性。 該博客將使您開(kāi)始思考如何在搜索中使用它們。
一個(gè)例子
首先,讓我們?cè)谶@里縮小一下范圍。 在很多情況下,使用n-gram可能是指搜索句子,而您的gram則是指句子中的單詞。 但是對(duì)于今天,我想集中討論單個(gè)單詞的細(xì)分。 n元語(yǔ)法世界中的單個(gè)單詞稱為帶狀皰疹。
讓我們進(jìn)一步縮小自己的范圍,假設(shè)我們想使用此搜索進(jìn)行近似匹配。 在應(yīng)用程序中,要搜索單詞(名稱,用戶名)或類似于單詞的數(shù)據(jù)(電話號(hào)碼),然后以與搜索單詞緊密匹配的形式向搜索者提供更多信息,這并不少見(jiàn)。 在這里,我們還希望部分匹配該單詞,而不是總是在前面,也不總是在結(jié)尾。
為了便于參考,請(qǐng)假裝我們有一個(gè)可以按名稱查找動(dòng)物的站點(diǎn)。 也許這是獸醫(yī)辦公室的前線,而該辦公室希望首先以寵物的名字進(jìn)行所有查找。 當(dāng)然,您可能會(huì)發(fā)現(xiàn)自己Swift擴(kuò)大了搜索范圍,以包括其他條件,但舉個(gè)例子,假設(shè)該辦公室的所有愛(ài)狗人士都瘋了,必須使用狗的名字。
分析儀
現(xiàn)在讓我們考慮一下分析儀的需求。 首先,我們已經(jīng)知道我們想要某種n-gram。 我們想要部分匹配。 其次,上面我們已經(jīng)決定要搜索單詞內(nèi)的部分匹配項(xiàng)。 在這種情況下,這將僅在一定程度上,正如我們稍后將看到的那樣,但是現(xiàn)在我們可以確定我們需要NGram令牌生成器,而不是僅保留從令牌開(kāi)頭開(kāi)始保留n-gram的Edge NGram令牌生成器。
ElasticSearch Ngrams允許最小和最大克數(shù)。 從最小值開(kāi)始,我們要匹配多少個(gè)名字? 好的,默認(rèn)值為1,但是由于我們已經(jīng)在處理單個(gè)單詞的數(shù)據(jù),所以如果我們使用一個(gè)字母(一個(gè)字母組合),我們肯定會(huì)得到太多的結(jié)果。 實(shí)際上,同樣的事情也將適用于二元組。 但是,足夠多的人養(yǎng)著三個(gè)字母的寵物,我們最好不要走,否則我們可能永遠(yuǎn)不會(huì)在搜索結(jié)果中返回名為“ Ace”和“ Rex”的幼犬。 現(xiàn)在我們知道我們的最小克數(shù)將是3。 最大克呢? 默認(rèn)值為2,我們已經(jīng)超過(guò)了最小值。 我們的目標(biāo)是盡可能多地包含潛在的準(zhǔn)確匹配項(xiàng),但在索引大小存儲(chǔ)方面仍然不會(huì)發(fā)瘋。
考慮選擇一個(gè)過(guò)大的數(shù)字(例如52),并為3個(gè)字符至52個(gè)字符之間的所有可能可能性分解名稱,您會(huì)發(fā)現(xiàn)隨著數(shù)據(jù)的增長(zhǎng),這很快就會(huì)加起來(lái)。 這里有些妥協(xié),因?yàn)樵谀承┣闆r下,您最終可能會(huì)排除超出最大語(yǔ)法的數(shù)據(jù)。
解決此排除問(wèn)題的方法有兩種,一種是包含您的字段的第二個(gè)映射并使用其他分析器(例如標(biāo)準(zhǔn)分析器),或者使用第二種映射并受益于精確匹配的速度和準(zhǔn)確性字詞查詢。
在我們的案例中,我們將利用將單獨(dú)的分析器用于搜索和索引的功能。 我們假設(shè)最大值之后的數(shù)據(jù)與我們的搜索無(wú)關(guān),在這種情況下,它極有可能與搜索無(wú)關(guān)。
因此,這里我們創(chuàng)建索引,然后設(shè)置自定義分析器。 關(guān)于整體內(nèi)容,這里的示例將有些簡(jiǎn)單,但是我希望它們有助于理解。
注意:稍微偏離主題,但是在現(xiàn)實(shí)生活中,您將需要以一種更可重用的方式進(jìn)行操作,例如模板,以便您可以輕松使用別名和版本并更新索引,但是為此例如,我只是展示了卷曲索引創(chuàng)建的最簡(jiǎn)單設(shè)置。
這是我們的第一個(gè)分析器,創(chuàng)建一個(gè)自定義分析器,并使用ngram_tokenizer和我們的設(shè)置。 如果您在這里,則可能知道這一點(diǎn),但是令牌生成器用于將字符串分解為術(shù)語(yǔ)或令牌流。 您可以根據(jù)需要在此處添加空格和許多其他選項(xiàng):
curl -XPUT 'localhost:9200/searchpets' -d '{"settings" : {"analysis" : {"analyzer" : {"ngram_analyzer" : {"tokenizer" : "ngram_tokenizer"}},"tokenizer" : {"ngram_tokenizer" : {"type" : "nGram","min_gram" : "3","max_gram" : "8"}}}}}'我們對(duì)此索引創(chuàng)建的響應(yīng)為{“ acknowledged”:true}。 優(yōu)秀的。
好了,既然有了索引,使用新的分析儀時(shí)數(shù)據(jù)將是什么樣?
curl -XGET'localhost:9200/searchpets/_analyze?analyzer=ngram_analyzer' -d 'Raven'響應(yīng)是:
{"tokens":[{"token":"Rav","start_offset":0,"end_offset":3,"type":"word","position":1},{"token":"Rave","start_offset":0,"end_offset":4,"type":"word","position":2},{"token":"Raven","start_offset":0,"end_offset":5,"type":"word","position":3},{"token":"ave","start_offset":1,"end_offset":4,"type":"word","position":4},{"token":"aven","start_offset":1,"end_offset":5,"type":"word","position":5},{"token":"ven","start_offset":2,"end_offset":5,"type":"word","position":6}]}這是合理的。 所有令牌都在3到5個(gè)字符之間生成(因?yàn)閱卧~少于8個(gè),所以很明顯)。
好的,太好了,現(xiàn)在將其應(yīng)用于字段。 而且,是的,您絕對(duì)可以一步一步完成所有操作,我只是將其分解。
$ curl -XPUT 'http://localhost:9200/searchpets/_mapping/pet' -d ' {"pet": {"properties": {"name": {"type": "string","analyzer": "ngram_analyzer"}}} } '我們?cè)诂F(xiàn)場(chǎng)測(cè)試分析:
curl -XGET 'http://localhost:9200/searchpets/_analyze?field=pet.name' -d 'Raven';再一次,我們得到了我們期望的結(jié)果:
{"tokens":[{"token":"Rav","start_offset":0,"end_offset":3,"type":"word","position":1},{"token":"Rave","start_offset":0,"end_offset":4,"type":"word","position":2},{"token":"Raven","start_offset":0,"end_offset":5,"type":"word","position":3},{"token":"ave","start_offset":1,"end_offset":4,"type":"word","position":4},{"token":"aven","start_offset":1,"end_offset":5,"type":"word","position":5},{"token":"ven","start_offset":2,"end_offset":5,"type":"word","position":6}]}現(xiàn)在,假設(shè)我已經(jīng)繼續(xù)并在此處添加了一些記錄,并針對(duì)以下內(nèi)容運(yùn)行簡(jiǎn)單的匹配查詢:{“ query”:{“ match”:{“ name”:“ Pegasus”}}}。
利用我的數(shù)據(jù),我們可以得到以下信息:
"hits": {"total": 2,"max_score": 0.29710895,"hits": [{"_index": "searchpets","_type": "pet","_id": "3","_score": 0.29710895,"_source": {"name": "Pegasus"}},{"_index": "searchpets","_type": "pet","_id": "2","_score": 0.0060450486,"_source": {"name": "Degas"}}] } }我們獲得最接近的匹配以及可能實(shí)際上是用戶正在尋找的關(guān)閉選項(xiàng)。
定制分析儀
好的,但是現(xiàn)在我們正在使用一個(gè)非常基本的分析器案例。 如果我們需要一個(gè)自定義分析器,以便能夠處理在搜索和索引上需要不同的分詞器的情況,該怎么辦? 如果我們想用關(guān)鍵字標(biāo)記器來(lái)限制搜索怎么辦?
讓我們對(duì)其進(jìn)行更改,以使用針對(duì)n元語(yǔ)法的過(guò)濾器來(lái)設(shè)置自定義分析器。 由于我們?cè)谙乱淮嗡阉髦惺褂昧藅okenizer關(guān)鍵字和match查詢,因此在顯示的這些測(cè)試用例中,此處的結(jié)果實(shí)際上與之前的結(jié)果相同,但是您會(huì)注意到它們的評(píng)分方式有所不同。
$ curl -XPUT 'localhost:9200/searchpets' -d '{"settings": {"analysis": {"analyzer": {"namegrams": {"type": "custom","tokenizer": "keyword","filter": ["ngrams_filter"]}},"filter": {"ngrams_filter": {"type": "ngram","min_gram": 3,"max_gram": 8}}}} }'現(xiàn)在,我們像以前一樣添加映射和數(shù)據(jù):
curl -XPUT 'http://localhost:9200/searchpets/_mapping/pet' -d ' {"pet": {"properties": {"name": {"type": "string","analyzer": "namegrams"}}} } '我運(yùn)行另一個(gè)匹配查詢:{“ query”:{“ match”:{“ name”:“ Pegasus”}}},響應(yīng)為:
hits": { "total": 2, "max_score": 1.1884358, "hits": [{"_index": "searchpets","_type": "pet","_id": "2","_score": 1.1884358,"_source": {"name": "Pegasus"}},{"_index": "searchpets","_type": "pet","_id": "3","_score": 0.08060065,"_source": {"name": "Degas"}} ] }因此,我們進(jìn)行了設(shè)置,并基于關(guān)鍵字標(biāo)記器和n-grams過(guò)濾器獲得了期望的結(jié)果和評(píng)分。 假設(shè)我們正在做一些更復(fù)雜的查詢。 我們可能還添加了其他一些過(guò)濾器或標(biāo)記器。 情況看起來(lái)不錯(cuò),對(duì)嗎? 好吧,差不多。
我前面提到的所有這些要記住的一個(gè)小因素。 我們有一個(gè)最大的8克。 那么,當(dāng)我們擁有一個(gè)超過(guò)該大小的名稱作為搜索條件時(shí),會(huì)發(fā)生什么呢? 好吧,根據(jù)您的搜索,您可能不會(huì)獲得任何數(shù)據(jù)。
您可能沒(méi)有想到這里會(huì)發(fā)生什么! 您如何避免這種情況? 一種方法是使用不同的index_analyzer和search_analyzer。 拆分這些內(nèi)容可以使您更好地控制搜索。
因此,假設(shè)我們對(duì)原始搜索所說(shuō)的一切都是真實(shí)的,那么您的最終設(shè)置將是這樣。 我不會(huì)深入探討查詢本身的詳細(xì)信息,但是我們將假定它將使用指定的search_analyzer(我建議閱讀ES文檔中有關(guān)如何選擇分析器進(jìn)行搜索的層次結(jié)構(gòu))。
注意:這里的search_ngram分析器上的小寫(xiě)標(biāo)記器會(huì)標(biāo)準(zhǔn)化標(biāo)記文本,因此所有數(shù)字都將被剝離。 此示例適用于此示例,但是使用不同的數(shù)據(jù)可能會(huì)導(dǎo)致意外的結(jié)果。
$ curl -XPUT 'localhost/searchpets' -d '{"settings": {"analysis": {"analyzer": {"namegrams": {"type": "custom","tokenizer": "keyword","filter": ["ngrams_filter"]},"search_ngram": {"type": "custom","tokenizer": "lowercase","filter": ["truncate_filter"]}},"filter": {"ngrams_filter": {"type": "ngram","min_gram": 3,"max_gram": 8},"truncate_filter": {"type": "truncate","length": 8}}}} } ’然后,最后,我們?cè)俅卧O(shè)置映射:
curl -XPUT 'http://localhost:9200/searchpets/_mapping/pet' -d ' {"pet": {"properties": {"name": {"type": "string","index_analyzer": "namegrams","search_analyzer": "search_trigram"}}} }'最后的想法
那里有。 但是,這使得假設(shè)超過(guò)8個(gè)字符的數(shù)據(jù)不太重要。 如果您要擁有比最大克數(shù)更大的數(shù)據(jù),并且類似的數(shù)據(jù),您可能會(huì)發(fā)現(xiàn)自己需要進(jìn)一步調(diào)整。
在Elastisearch中使用n-gram搜索可以做的事情有很多可能性。 我希望這可以讓您開(kāi)始思考如何在搜索中使用它們。
翻譯自: https://www.javacodegeeks.com/2015/11/anatomy-of-setting-up-an-elasticsearch-n-gram-word-analyzer.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的设置Elasticsearch N-Gram字分析器的过程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java胜任理由_Java在几乎所有方面
- 下一篇: jigsaw kaggle_使用Proj