Elasticsearch同義詞配置

很多情況下,我們希望在搜索時,有時能夠使用一個詞的同義詞來進行補充搜索,這樣我們能搜索出來更多相關的內(nèi)容。這個場景可以通過 text analysis 來幫助我們生成同義詞。那么在進行同義詞搜索時,我們有如下的幾種方案:

通過修改setting配置同義詞

首先,我們來創(chuàng)建一個具有如下 anaylzer 及 mapping 的一個索引:


PUT myindex

{

  "settings": {

    "analysis": {

      "filter": {

        "my_synonyms": {

          "type": "synonym_graph",

          "synonyms": [

            "清新,可愛,動漫,粉色,浪漫"

          ]

        }

      },

      "analyzer": {

        "my_analyzer": {

          "type": "custom",

          "tokenizer": "ik_max_word",

          "filter":[

            "lowercase",

            "my_synonyms"

          ]

        }

      }

    }

  },

  "mappings": {

    "properties": {

      "title": {

        "type": "text",

        "analyzer": "ik_max_word",

        "search_analyzer": "my_analyzer"

      }

    }

  }

}

在上面,我們使用 synonym_graph 過濾器對 quey 時的詞進行過濾。在這個過濾器中,我們把如下的一個詞都視為同義詞:

清新,可愛,動漫,粉色,浪漫

在mapping 中,我們定義了 search_analyzer 為 my_analyzer,也就是說在 query 時,它會對所有的詞進行分詞。但凡有任何一個詞是 '清新,可愛,動漫,粉色,浪漫' 其中的一個,它都將被視為同義詞。

我們首先來創(chuàng)建一個文檔:


PUT myindex/_doc/1

{

  "title": "通用清新粉色高端醫(yī)院美容企業(yè)春暖花開職等你來招聘"

}

運行上面的指令,我們將創(chuàng)建一個 title 為 '通用清新粉色高端醫(yī)院美容企業(yè)春暖花開職等你來招聘' 的文檔。

接下來,我們做如下的查詢:


GET myindex/_search

{

  "query": {

    "match": {

      "title": "粉色"

    }

  }

}

那么顯示的結果是:


{

  "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" : {

          "title" : "通用清新粉色高端醫(yī)院美容企業(yè)春暖花開職等你來招聘"

        }

      }

    ]

  }

}

可能有人說了,這是因為上面的 title 里本身就含有 '粉色', 所以上面的結果證明不了什么。接下來,我們進行如下的搜索:


GET myindex/_search

{

  "query": {

    "match": {

      "title": "浪漫"

    }

  }

}

結果,我們可以發(fā)現(xiàn),我們同樣顯示上面的搜索的結果。這個說明了這個同義詞的搜索是成功的。

接下來,我們想通過搜索 '素雅' 也能搜索出'清新'來,那么我怎么做呢?

我們來執(zhí)行如下的命令:


POST myindex/_close

PUT myindex/_settings

{

  "analysis": {

    "filter": {

      "my_synonyms": {

        "type": "synonym_graph",

        "synonyms": [

          "清新,素雅,可愛,動漫,粉色,浪漫"

        ]

      }

    },

    "analyzer": {

      "my_analyzer": {

        "type": "custom",

        "tokenizer": "standard",

        "filter": [

          "lowercase",

          "my_synonyms"

        ]

      }

    }

  }

}

POST myindex/_open

我們可以通過更新 setting 來實現(xiàn)這個。在上面請注意:當我們更新一個索引的 index 時,我們必須先把它關掉,等設置好后,在重新打開。否則會有錯誤。那么經(jīng)過上面的修改后,我們重新運行如下的搜索:


GET myindex/_search

{

  "query": {

    "match": {

      "title": "素雅"

    }

  }

}

那么上面的搜索結果將會顯示我們之前顯示的結果。在這里 ‘素雅’ 也就是和之前的其它詞都是同義詞。

通過修改文件配置同義詞

有人可能覺得上面在 settings 里配置太多的同義詞很麻煩,而且關閉索引會影響線上查詢(可以放到凌晨進行)。按照 Elastic 的官方文檔,我們可以把所有的同義詞放到一個文檔中。首先,我們在 Elasticsearch 的 config 目錄中,創(chuàng)建一個叫做 analysis 的子目錄,然后創(chuàng)建一個叫做 synonyms.txt 的文檔,而它的內(nèi)容如下:

$ pwd

/Users/liuxg/elastic/elasticsearch-7.8.0/config/analysis

$ cat synonyms.txt

"清新,素雅,可愛,動漫,粉色,浪漫",

"elk, elastic stack"

在這里,我們多添加了一個 elk, elastic stack 的同義詞。我們來創(chuàng)建一個新的索引:


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"

      }

    }

  }

}

運行完上的指令后,我們來創(chuàng)建一個文檔:


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

總結

在上面,我們展示了兩種方法進行同義詞的查詢。在實際的使用中,你可以根據(jù)自己的情況適當進行選擇。當然,我們有可以把上面的兩種方法進行同時并用。通過這兩種方法,也有可能會造成搜索的精確度的問題。這個是你必須要想清楚的。這個就像我們?nèi)鼍W(wǎng)打魚一樣,把網(wǎng)撒大了,撈上來的也有可能不是我們想要的。
需要注意的是如果我們想在索引階段就對同義詞token進行索引的話,那么需要使用synonym分析器而不是synonym_graph

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容