Elasticsearch:使用同義詞 synonyms 來提高搜尋效率
阿里雲官方映象站:
https://developer.aliyun.com/mirror/?&utm_content=g_1000304576
在我們的很多情況下,我們希望在搜尋時,有時能夠使用一個詞的同義詞來進行搜尋,這樣我們能搜尋出來更多相關的內容。我們可以透過 text analysis 來幫助我們形成同義詞。文字分析通常應用於你建立索引時的所有文件以及傳送給 Elasticsearch 的所有查詢。在進行同義詞搜尋時,我們有如下的幾種方案:
-
在建立索引時 (indexing),透過 analyzer 建立 synonyms 的反向索引 (inverted index)
-
在 query 時,透過 search analyzer 對查詢的詞建立 synonyms
-
在 indexing 及 query 時,同時建立反向索引中的 synonym 及在 query 時為查詢的詞建立 synonyms
那麼在實際的使用中,我們到底是用上述的哪種方案呢?在下面的例子中,你將看到在 query 時使用 synonym 會更加靈活,並且更容易讓我們更新同義詞的名單已經更好地支援 multi-word synonyms。
在今天的文章中,我們將分別論述。
在 query 時對詞進行同義詞解析
首先,我們來建立一個具有如下 anaylzer 及 mapping 的一個索引:
PUT myindex { "settings": { "analysis": { "filter": { "my_synonyms": { "type": "synonym_graph", "synonyms": [ "China, chn, PRC, People's Republic of China" ] } }, "analyzer": { "my_analyzer": { "type": "custom", "tokenizer": "standard", "filter":[ "lowercase", "my_synonyms" ] } } } }, "mappings": { "properties": { "content": { "type": "text", "analyzer": "standard", "search_analyzer": "my_analyzer" } } } }
在上面,我們使用 synonym_graph 過濾器對 quey 時的詞進行過濾。在這個過濾器中,我們把如下的一個詞都視為同義詞:
China, chn, PRC, People’s Republic of China
在 mapping 中,我們定義了 search_analyzer 為 my_analyzer,也就是說在 query 時,它會對所有的詞進行分詞。但凡有任何一個詞是 China, chn, PRC, People’s Republic of China 其中的一個,它都將被視為同義詞。
我們首先來建立一個文件:
PUT myindex/_doc/1 { "content": "I like People's Republic of China" }
執行上面的指令,我們將建立一個 content 為 I like People’s Republic of China 的文件。
接下來,我們做如下的查詢:
GET myindex/_search { "query": { "match": { "content": "China" } } }
那麼顯示的結果是:
{ "took" : 256, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 1.4384104, "hits" : [ { "_index" : "myindex", "_type" : "_doc", "_id" : "1", "_score" : 1.4384104, "_source" : { "content" : "I like People's Republic of China" } } ] } }
可能有人說了,這是因為上面的 content 裡本身就含有 China, 所以上面的結果證明不了什麼。接下來,我們進行如下的搜尋:
GET myindex/_search { "query": { "match": { "content": "prc" } } }
結果,我們可以發現,我們同樣顯示上面的搜尋的結果。這個說明了這個同義詞的搜尋是成功的。
接下來,我們想搜尋 silk road 也能搜尋出中國來,那麼我怎麼做呢?
我們來執行如下的命令:
POST myindex/_close PUT myindex/_settings { "analysis": { "filter": { "my_synonyms": { "type": "synonym_graph", "synonyms": [ "china, silk road, chn, PRC, People's Republic of China" ] } }, "analyzer": { "my_analyzer": { "type": "custom", "tokenizer": "standard", "filter": [ "lowercase", "my_synonyms" ] } } } } POST myindex/_open
我們可以透過更新 setting 來實現這個。在上面請注意:當我們更新一個索引的 index 時,我們必須先把它關掉,等設定好後,在重新開啟。否則會有錯誤。那麼經過上面的修改後,我們重新執行如下的搜尋:
GET myindex/_search { "query": { "match": { "content": "silk road" } } }
那麼上面的搜尋結果將會顯示我們之前顯示的結果。在這裡 silk road 也就是和之前的其它詞都是同義詞。
有人可能覺得上面在 settings 裡配置太多的同義詞很麻煩(如果同義詞很多的話)。按照 Elastic 的官方文件,我們可以把所有的同義詞放到一個文件中。首先,我們在 Elasticsearch 的 config 目錄中,建立一個叫做 analysis 的子目錄,然後建立一個叫做 synonyms.txt 的文件,而它的內容如下:
$ pwd /Users/liuxg/elastic/elasticsearch-7.8.0/config/analysis liuxg:analysis liuxg$ cat synonyms.txt "china, silk road, chn, PRC, People's Republic of China", "elk, elastic stack"
在這裡,我們多新增了一個 elk, elastic stack 的同義詞。我們來建立一個新的索引:
PUT myindex1 { "settings": { "analysis": { "filter": { "my_synonyms": { "type": "synonym_graph", "synonyms_path": "analysis/synonyms.txt" } }, "analyzer": { "my_analyzer": { "type": "custom", "tokenizer": "standard", "filter":[ "lowercase", "my_synonyms" ] } } } }, "mappings": { "properties": { "content": { "type": "text", "analyzer": "standard", "search_analyzer": "my_analyzer" } } } }
執行完上的指令後,我們來建立一個文件:
PUT myindex1/_doc/1 { "content": "I love elastic stack" }
然後我們做如下的搜尋:
GET myindex1/_search { "query": { "match": { "content": "elk" } } }
上面的搜尋結果顯示:
{ "took" : 451, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 0.5753642, "hits" : [ { "_index" : "myindex1", "_type" : "_doc", "_id" : "1", "_score" : 0.5753642, "_source" : { "content" : "I love elastic stack" } } ] } }
顯然,我可以看到搜尋 elk,我們就可以搜尋到含有 elastic stack 的文件。
在實際的使用中,如果我們更新 synonyms.txt 檔案,那麼,我們可以使用如下的 API 來進行更新:
POST myindex1/_reload_search_analyzers
在建立索引時建立同義詞
針對這種情況,我們可以在建立索引的時候,就把同義詞建立好。這樣,我們可以在 query 時,不使用同義詞解析。在這種情況下,我們可以使用 synonym 過濾器,而不是 synonym_graph 過濾器。
我們接下來使用如下的命令來建立一個新的索引:
PUT myindex2 { "settings": { "analysis": { "filter": { "my_synonyms": { "type": "synonym", "synonyms": [ "china, silk road, chn, PRC, People's Republic of China", "elk, elastic stack" ] } }, "analyzer": { "my_analyzer": { "tokenizer": "standard", "filter": [ "lowercase", "my_synonyms" ] } } }, "number_of_shards": 1 }, "mappings": { "properties": { "content": { "type": "text", "analyzer": "my_analyzer" } } } }
在上面,我們使用了 my_analyzer 作為 myindex2 在索引時使用的分詞器。它將使用 synonym 過濾器,並把如下的詞視為同義詞:
"china, silk road, chn, PRC, People's Republic of China", "elk, elastic stack"
我們可以使用如下的方法來測試這個 analyzer:
POST myindex2/_analyze { "text": "I like elk a lot", "analyzer": "my_analyzer" }
上面的命令顯示的結果是:
{ "tokens" : [ { "token" : "i", "start_offset" : 0, "end_offset" : 1, "type" : "<ALPHANUM>", "position" : 0 }, { "token" : "like", "start_offset" : 2, "end_offset" : 6, "type" : "<ALPHANUM>", "position" : 1 }, { "token" : "elk", "start_offset" : 7, "end_offset" : 10, "type" : "<ALPHANUM>", "position" : 2 }, { "token" : "elastic", "start_offset" : 7, "end_offset" : 10, "type" : "SYNONYM", "position" : 2 }, { "token" : "a", "start_offset" : 11, "end_offset" : 12, "type" : "<ALPHANUM>", "position" : 3 }, { "token" : "stack", "start_offset" : 11, "end_offset" : 12, "type" : "SYNONYM", "position" : 3 }, { "token" : "lot", "start_offset" : 13, "end_offset" : 16, "type" : "<ALPHANUM>", "position" : 4 } ] }
你可以看到,儘管在測試的 text 沒有 elastic stack,只有 elk,但是顯示的結果了含有 elastic 及 stack 這兩個 token。
我們接下來使用如下的命令來建立一個文件:
PUT myindex2/_doc/1 { "content": "I like elk a lot" }
我們使用如下的查詢:
GET myindex2/_validate/query?rewrite=true { "query": { "match": { "content": "elastic stack" } } }
上面顯示的結果是:
{ "_shards" : { "total" : 1, "successful" : 1, "failed" : 0 }, "valid" : true, "explanations" : [ { "index" : "myindex2", "valid" : true, "explanation" : """content:"elastic stack" content:elk""" } ] }
從上面的顯示的結果來看,當我們搜尋 elastic stack 時,它同時匹配 content: “elastic stack” 以及 content: elk。也就是說,如果文件裡含有 elk,那麼這個文件也將被搜尋到。我們做如下的搜尋:
GET myindex2/_search { "query": { "match": { "content": "elastic stack" } } }
那麼上面的命令顯示的結果是:
{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 0.977273, "hits" : [ { "_index" : "myindex2", "_type" : "_doc", "_id" : "1", "_score" : 0.977273, "_source" : { "content" : "I like elk a lot" } } ] } }
顯然它已經把我們的想要的結果搜尋出來了。
總結
在上面,我們展示了兩種方法進行同義詞的查詢。在實際的使用中,你可以根據自己的情況適當進行選擇。當然,我們有可以把上面的兩種方法進行同時並用。透過這兩種方法,也有可能會造成搜尋的精確度的問題。這個是你必須要想清楚的。這個就像我們撒網打魚一樣,把網撒大了,撈上來的也有可能不是我們想要的。
原文連結:https://elasticstack.blog.csdn.net/article/details/108003222
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70003733/viewspace-2840424/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Laravel 使用 Elasticsearch 全域性搜尋LaravelElasticsearch
- Elasticsearch 使用不同分詞器導致搜尋排名的問題Elasticsearch分詞
- BM42:語義搜尋與關鍵詞搜尋結合
- Elasticsearch常用搜尋Elasticsearch
- Elasticsearch——全文搜尋Elasticsearch
- elasticsearch搜尋商品Elasticsearch
- Elasticsearch 向量搜尋Elasticsearch
- grep 命令系列:使用 grep 命令來搜尋多個單詞
- 單詞搜尋
- elasticsearch 搜尋引擎工具的高階使用Elasticsearch
- 使用elasticsearch搭建自己的搜尋系統Elasticsearch
- 在 Spring Boot 中使用搜尋引擎 ElasticsearchSpring BootElasticsearch
- 使用 Laravel Scout + ElasticSearch 實現全文搜尋LaravelElasticsearch
- ElasticSearch全文搜尋引擎Elasticsearch
- elasticsearch之拼音搜尋Elasticsearch
- Elasticsearch 為了搜尋Elasticsearch
- 搜尋引擎es-分詞與搜尋分詞
- Elasticsearch 近義詞詞庫配置Elasticsearch
- Elasticsearch(ES)的高階搜尋(DSL搜尋)(上篇)Elasticsearch
- Elasticsearch(ES)的高階搜尋(DSL搜尋)(下篇)Elasticsearch
- Elasticsearch 的配置與使用,為了全文搜尋Elasticsearch
- 像使用 Laravel Query 一樣的搜尋 ElasticsearchLaravelElasticsearch
- elasticsearch(五)---分散式搜尋Elasticsearch分散式
- 認識搜尋引擎 ElasticsearchElasticsearch
- (1)分散式搜尋ElasticSearch認識ElasticSearch分散式Elasticsearch
- 在大資料量下提高查詢效率的方法—ES搜尋引擎大資料
- 79. 單詞搜尋
- 單詞搜尋問題
- Laravel5.5 使用 Elasticsearch 做引擎,scout 全文搜尋LaravelElasticsearch
- Nebula 基於 ElasticSearch 的全文搜尋引擎的文字搜尋Elasticsearch
- 搜尋引擎ElasticSearch18_ElasticSearch簡介1Elasticsearch
- Linux 命令列下搜尋工具大盤點,效率提高不止一倍!Linux命令列
- Elasticsearch 實現簡單搜尋Elasticsearch
- Laravel + Elasticsearch 實現中文搜尋LaravelElasticsearch
- 【elasticsearch】搜尋過程詳解Elasticsearch
- Elasticsearch搜尋資料彙總Elasticsearch
- 自然搜尋排名該如何提高?
- solr搜尋分詞優化Solr分詞優化