日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

倒排索引、分词、同义词

發布時間:2025/3/17 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 倒排索引、分词、同义词 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

倒排索引

  • 正排索引:文檔ID =>文檔內容和單詞
  • 倒排索引:詞條 =>文檔ID
  • 倒排索引組成:
    • 詞條字典(Term Dictionary),記錄所有的詞條與倒排列表的映射關系。這個字典很大,通過B+樹或哈希拉鏈法實現,以滿足高性能的插入與查詢。
    • 倒排列表(Posting List),由倒排索引項組成,包含如下信息:
      • 文檔ID
      • 詞頻(TF):該單詞在文檔中出現的次數,用于相關性評分
      • 位置(Position):單詞在文檔中分詞的位置(也就是第幾個分詞),用于語句搜索(phrase query)
      • 偏移(Offset):記錄單詞的開始結束位置,實現高亮顯示(從第幾個字符開始,到第幾個字符結束)
  • ES的倒排索引:
    • ES文檔的每個字段,默認都有自己的倒排索引
    • 可以通過mappings,指定某些字段不做索引,以節省存儲空間,但會導致該字段無法被搜索。

分詞

文本分析(Analysis),就是把全文轉換成一系列詞條(term / token)的過程(也叫分詞)。文本分析是通過分詞器(Analyzer)實現的。

https://www.elastic.co/guide/en/elasticsearch/reference/7.2/analysis.html

分詞器有兩個作用:

  • 數據寫入時轉換詞條
  • 分析查詢語句

ES內置了多種分詞器:https://www.elastic.co/guide/en/elasticsearch/reference/7.2/analysis-analyzers.html

在mapping中,每個text字段都可以指定專門的分詞器:

PUT {index} {"mappings": {"properties": {"{field}": {"type": "text","analyzer": "{standard}" // 指定分詞器}}} }

說明:已經存在的索引執行上述操作會報錯。可以在創建索引時指定。standard分詞器是默認的分詞器。

通常情況下,創建(index)和查詢(search)時,應該使用同樣的分詞器。執行全文檢索時,比如match查詢,會在mapping中為每個字段查找分詞器。在查詢具體字段時使用何種分詞器,遵循如下查找順序:

  • 查詢條件有指定analyzer
  • mapping中的search_anylyzer參數
  • mapping中的analyzer參數
  • 索引設置中的default_search
  • 索引設置中的default
  • standard分詞器

分詞器由以下三部分組合而成:

  • Character Filters:處理原始文本,比如去除html標簽。一個分詞器可以沒有或擁有多個char filter。

  • Tokenizer:接收上一步處理后的文本流,按照規則切分出詞條并輸出,比如:

    • whitespace 按空格切分詞條
    • keyword 不做分詞,直接作為關鍵詞
    • path_hierarchy, 按路徑切分,保證搜索任意一級目錄都可以搜索到結果

    更多類別參考官網,每個分詞器必須有一個tokenizer。

  • Token Filters:接收詞條流,進行再加工,可能會添加、刪除、或者變更詞條。比如:

    • lowercase 將所有的詞條轉為小寫
    • stop將停頓詞(比如,the, in, on)從詞條流中移除
    • synonym往詞條流中引入同義詞
    • multiplexer 一個單詞觸發多個詞條(應用多個過濾器,每個過濾器觸發一個),重復的詞條會被去除。建議:將同義詞過濾器追加到每個multiplexer過濾器列表后面,不要放在multiplexer之后,以避免異常。建議具體見官網底部的note

    更過token filter類別可以參考官網,一個分詞器可以沒有或擁有多個token filter

通過組合以上三部分,我們也可以自定義分詞器。

###analyze接口

analyze接口可以用來執行文本分析處理,并查看分詞結果,比如:

GET _analyze {"analyzer": "standard","text": "hello world" }

使用standard分詞器對文本進行分詞,返回結果如下:

{"tokens" : [{"token" : "hello","start_offset" : 0,"end_offset" : 5,"type" : "<ALPHANUM>","position" : 0},{"token" : "world","start_offset" : 6,"end_offset" : 11,"type" : "<ALPHANUM>","position" : 1}] }

自定義分詞

也可以自己定義分詞器,其實就是組合tokenizer, token filter 和 char filer,比如:

示例1:自定義token filter

POST _analyze {"tokenizer": "standard","filter": [ "lowercase", "asciifolding" ],"text": "Is this déja vu?" }

示例2:自定義char_filter

POST _analyze {"tokenizer": "standard","char_filter": [{"type": "mapping","mappings": ["- => _"] // 將中劃線替換為下劃線, 甚至可以將emoji表情替換為單詞}],"text": "123-456, hello-world" }// 結果如下: {"tokens" : [{"token" : "123_456","start_offset" : 0,"end_offset" : 7,"type" : "<NUM>","position" : 0},{"token" : "hello_world","start_offset" : 9,"end_offset" : 20,"type" : "<ALPHANUM>","position" : 1}] }

也可以為某個索引(集)自定義分詞器:

put forum {"settings": {"analysis": {"analyzer": {"my_analyzer": { // 自定義分詞器名字"type": "custom","tokenizer": "standard","filter": ["lowercase","asciifolding"]}}}},"mappings": {"properties": {"title": {"type": "text","analyzer": "my_analyzer" // 使用自定義分詞器}}} }

測試分詞效果:

GET forum/_analyze {"analyzer": "my_analyzer","text": "Mr déjà" }

分詞結果如下:

{"tokens" : [{"token" : "mr","start_offset" : 12,"end_offset" : 14,"type" : "<ALPHANUM>","position" : 3},{"token" : "deja","start_offset" : 15,"end_offset" : 19,"type" : "<ALPHANUM>","position" : 4}] }

mapping自定義分詞器完全版:

{'settings': {'analysis': {'analyzer': { # 自定義analyzer: 可以使用下面自定義的tokenizer, char_filter,token_filter 等內容'my_analyzer': {'type': 'custom','char_filter': 'my_char_flt','tokenizer': 'my_tokenizer','filter': ['my_flt'], # token_filter}},'char_filter': { # 自定義 char_filter'my_char_flt': {}},'tokenizer': { # 自定義 tokenizer'my_tokenizer': {}},'filter': { # 自定義 token_filter'my_flt': {'type': 'synonym','synonyms_path': 'xxxxx'}},# "search_analyzer": {} # 也可以定義搜索分詞器, 同analyzer},},'mappings': {'properties': {'content': {'type': 'text','analyzer': 'my_analyzer', # 使用自定義的分詞器'search_analyzer': 'ik_smart',}}} }

中文分詞

ES內置的中文分詞不好用,可以通過插件安裝,比如非常流行的ik分詞:

.\elasticsearch-plugin.bat install https://github.com/medcl/elasticsearch-ana lysis-ik/releases/download/v7.2.0/elasticsearch-analysis-ik-7.2.0.zip

裝好后重啟ES,查看插件列表:

GET _cat/plugins

返回剛剛安裝的ik插件

DESKTOP-L1E59GR analysis-ik 7.2.0

ik支持一些自定義配置,比如擴展詞典和熱詞更新。配置文件默認位置在es安裝目錄的configik目錄下。具體配置可以參考:https://github.com/medcl/elasticsearch-analysis-ik

安裝完成后,我們測試下效果:

GET _analyze {"analyzer": "ik_smart","text": "創新空間的不朽傳奇" }

分詞結果:

{"tokens" : [{"token" : "創新","start_offset" : 0,"end_offset" : 2,"type" : "CN_WORD","position" : 0},{"token" : "空間","start_offset" : 2,"end_offset" : 4,"type" : "CN_WORD","position" : 1},{"token" : "的","start_offset" : 4,"end_offset" : 5,"type" : "CN_CHAR","position" : 2},{"token" : "不朽","start_offset" : 5,"end_offset" : 7,"type" : "CN_WORD","position" : 3},{"token" : "傳奇","start_offset" : 7,"end_offset" : 9,"type" : "CN_WORD","position" : 4}] }

試試官網的例子,定義news索引的mapping:

PUT news {"mappings": {"properties": {"content": {"type": "text","analyzer": "ik_max_word", "search_analyzer": "ik_smart"}}} }

按照文檔說明,索引一些doc進去:

PUT news/_doc/4 {"content": "中國駐洛杉磯領事館遭亞裔男子槍擊 嫌犯已自首" }

進行高亮查詢:

POST news/_search {"query": {"match": {"content": "中國"}},"highlight": {"pre_tags": "<bold>","post_tags": "</bold>","fields": {"content": {}}} }

返回結果如下:

{"took" : 2,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 2,"relation" : "eq"},"max_score" : 0.642793,"hits" : [{"_index" : "news","_type" : "_doc","_id" : "3","_score" : 0.642793,"_source" : {"content" : "中韓漁警沖突調查:韓警平均每天扣1艘中國漁船"},"highlight" : {"content" : ["中韓漁警沖突調查:韓警平均每天扣1艘<bold>中國</bold>漁船"]}},{"_index" : "news","_type" : "_doc","_id" : "4","_score" : 0.642793,"_source" : {"content" : "中國駐洛杉磯領事館遭亞裔男子槍擊 嫌犯已自首"},"highlight" : {"content" : ["<bold>中國</bold>駐洛杉磯領事館遭亞裔男子槍擊 嫌犯已自首"]}}]} }

測試下來后,在索引階段,建議使用ik_max_word分詞器,能更靈活的切割詞條。

除了IK分詞,還可以使用THULAC分詞器,號稱準確率目前最高。不過目前只更新到6.4,不知道7.2能否使用。

搜索時指定分詞器

GET post001/_search {"query": {"match": {"content": {"query": "考研","analyzer": "standard"}}},"highlight": {"fields": {"content": {}}}}

同義詞圖過濾器 Synonym Graph Token Filter

synonym_graph詞條過濾器(token filter)用于處理同義詞。

注意:該過濾器僅適用于作為搜索分詞器的一部分。如果想在索引期間應用同義詞,需要使用標準的同義詞過濾器

同義詞可以使用配置文件指定,如下:

PUT /{index} {"settings": {"index" : {"analysis" : {"analyzer" : {"search_synonyms" : { // 自定義分詞器名字"tokenizer" : "whitespace","filter" : ["graph_synonyms"] // 使用自定義filter}},"filter" : {"graph_synonyms" : {"type" : "synonym_graph", // 指定類型為同義詞圖"synonyms_path" : "analysis/synonym.txt" // 指定同義詞詞庫位置}}}}} }

說明:同義詞詞庫的位置是相對于config目錄的相對地址。另外以下參數也是可用的:

  • expand 默認為true
  • leninet 默認為false,是否忽略同義詞配置的解析異常,記住,如果設置為true,只要那些無法被解析到同義詞規則會被忽略。如下示例:
PUT /{test_index} {"settings": {"index" : {"analysis" : {"analyzer" : {"synonym" : {"tokenizer" : "standard","filter" : ["my_stop", "synonym_graph"]}},"filter" : {"my_stop": {"type" : "stop","stopwords": ["bar"]},"synonym_graph" : {"type" : "synonym_graph","lenient": true,"synonyms" : ["foo, bar => baz"] // 手動定義同義詞映射}}}}} }

說明:bar在自定義的my_stop的filter中被剔除,但是在synonym_graph的filter中,foo => baz仍然被添加成功。但如果添加的是"foo, baz => bar", 那么什么也不會被添加到同義詞列表。這時因為映射到目標單詞"bar"本身作為停用詞已被剔除。相似的,如果映射是"bar, foo, baz"并且expand設置為false,那么不會添加任何同義詞映射,因為當expand為false時,目標映射是第一個單詞,也就是"bar"。但是如果expand=true,那么映射將會添加為"foo, baz => foo, baz",即所有詞相互映射,除了停用詞。

同義詞配置文件如下:

# 空行和#號開頭的都是注釋# 近義詞以 => 映射,這種映射會忽略模式中的 expand 參數 # 匹配到"=>"左側的詞條后,被替換為"=>"右側的詞條。 i-pod, i pod => ipod, sea biscuit, sea biscit => seabiscuit# 近義詞以逗號分隔,映射行為由模式中的expand參數決定。如此同樣的近義詞文件,可以用于不同的策略 ipod, i-pod, i pod foozball , foosball universe , cosmos lol, laughing out loud# 當expand==true, "ipod, i-pod, i pod" 等價于: ipod, i-pod, i pod => ipod, i-pod, i pod # 當expand==false, "ipod, i-pod, i pod" 僅映射第一個單詞, 等價于: ipod, i-pod, i pod => ipod# 多個同義詞映射將會合并 foo => foo bar foo => baz # 等價于: foo => foo bar, baz

雖然可以直接在filter中使用synonyms定義同義詞,比如:

PUT /test_index {"settings": {"index" : {"analysis" : {"filter" : {"synonym" : {"type" : "synonym_graph","synonyms" : [ // 直接定義"lol, laughing out loud","universe, cosmos"]}}}}} }

但是對于大型的同義詞集合,還是推薦使用synonyms_path參數在文件中定義。

測試

定義mapping

PUT article {"settings": {"index": {"analysis": {"analyzer": {"my_analyzer": {"tokenizer": "ik_max_word","filter": ["my_synonyms"]}},"filter": {"my_synonyms": {"type": "synonym_graph","synonyms_path": "analysis/synonyms.txt"}},"search_analyzer": "ik_smart"}}} }

在ES的config/analysis目錄下新建synonyms.txt文件,內容如下:

北京大學, 北大

索引一篇文檔:

PUT article/_doc/1 {"content": "北京大學今年考研一飛沖天" }

試著搜索:

GET article/_search {"query": {"match": {"content": {"query": "北大"}}} }

搜索結果:

{"took" : 0,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 1,"relation" : "eq"},"max_score" : 0.5753642,"hits" : [{"_index" : "article","_type" : "_doc","_id" : "1","_score" : 0.5753642,"_source" : {"content" : "北京大學今年考研一飛沖天"}}]} }

同義詞過濾器 Synonym Token Filter

同義詞過濾器配置示例:

PUT /test_index {"settings": {"index" : {"analysis" : {"analyzer" : {"my-synonym" : { // 自定義分詞器名字"tokenizer" : "whitespace","filter" : ["my_synonym_fltr"] // 指定過濾器}},"filter" : {"my_synonym_fltr" : { // 自定義同義詞過濾器名字"type" : "synonym", // type 為synonym,"synonyms_path" : "analysis/synonym.txt"}}}}} }

其實同義詞過濾器和以上面的同義詞圖過濾器配置用法都是一樣的。區別如下:

  • 前者type=synonym,后者type=synonym_graph
  • 前者可以在文檔索引期間使用,后者只能作為搜索分詞的一部分。

另外在同義詞圖中的測試,將type更改后,測試仍然適用。

總結

以上是生活随笔為你收集整理的倒排索引、分词、同义词的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。