全文檢索基本概念

来源:http://www.cnblogs.com/lane_cn/archive/2016/08/18/5783192.html
-Advertisement-
Play Games

1.分詞 全文檢索必須要分詞,所謂分詞就是把一句話切分成一個個單獨的詞。分詞有很多演算法,比如自然分詞、n-gram分詞、字典分詞等等。對中文來說沒有自然分隔符,一般採用字典分詞,再加上對人名、地名的特殊處理,提高分詞的準確性。 我們使用ik分片語件,ik有兩種分詞策略:smart策略、max wor ...


1.分詞

全文檢索必須要分詞,所謂分詞就是把一句話切分成一個個單獨的詞。分詞有很多演算法,比如自然分詞、n-gram分詞、字典分詞等等。對中文來說沒有自然分隔符,一般採用字典分詞,再加上對人名、地名的特殊處理,提高分詞的準確性。

我們使用ik分片語件,ik有兩種分詞策略:smart策略、max word策略。

例如這個句子:

1939年的德國,9歲的小女孩莉賽爾和弟弟被迫送往慕尼黑遠郊的寄養家庭。6歲的弟弟不幸死在了路途中。在冷清的葬禮後,莉賽爾意外得到她的第一本書《掘墓人手冊》。

 看一下分詞的結果,先看smart策略:

1939年/德國/9歲/小女孩/莉/賽/爾/和/弟弟/被迫/送往/慕尼黑/遠郊/寄養/家庭/6歲/弟弟/不幸/死/路/途中/冷清/葬禮/後/莉/賽/爾/意外/得/到她/第一/本書/掘墓人/手冊

 

Elasticsearch支持分詞介面,比如這個介面:

http://localhost:9200/index/_analyze?text=1939年的德國&analyzer=ik_smart

可以執行一個分詞計算,使用的分詞器是ik_smart。在分詞結果中可以看到每個詞的位置和類型。 

句子按照中文語法被分割成一個個詞,仔細觀察一下可以看到兩個現象:

1. 標點符號都不見了
2. 少了一些字,比如“的”、“在”、“了”

這個處理叫做“預處理”,預處理過程會去掉句子中的符號、停止詞(stop word),這兩種元素在檢索中沒有什麼作用,對排序還會造成很大的干擾,在索引的時候就被去除掉了。

對於英文等西方文字,由於詞之間存在自然分割,所以分詞的難度低,準確性高。拼音文字一般存在單複數、時態、詞性等詞尾的變化,比如make、made、makes,索引的時候還需要做詞形變換,全部處理成原型。

從分詞結果中還可以看到,一些分詞結果不准確,比如“1939年”、“得/到她”,因為分詞不准確,當用戶搜索“1939”、“得到”就檢索不到這個文檔,儘管文檔中出現了這些詞。還有“莉/賽/爾”,ik不能識別這個詞,分割成了三個獨立的字。如果用戶搜索“賽莉爾”,也能搜出文檔。

為了避免分詞不准確影響召回率的情況,可以使用max word策略:

1939/年/德國/9/歲/小女孩/小女/女孩/莉/賽/爾/和/弟弟/被迫/迫/送往/慕尼黑/慕/尼/黑/遠郊/郊/寄養/寄/養家/家庭/家/庭/6/歲/弟弟/不幸/死/路途/途中/途/中/冷清/冷/清/葬禮/葬/禮/後/莉/賽/爾/意外/得到/到她/第一本/第一/一本書/一本/一/本書/本/書/掘墓人/墓/人手/手冊/冊

max word多分出了很多詞,這樣就增加了檢索的召回率,但是正確率有所降低,也增加了索引的體積。

我們的策略是:對fulltext欄位使用max_word分詞策略進行索引。term檢索不對查詢詞做分詞處理,輸入什麼詞就檢索什麼詞。match_query檢索對查詢詞用smart策略。span_near_query檢索對查詢詞使用max_word策略,確保分詞結果一致。這樣做準確率和召回率都比較合適。

2.反向索引

反向索引也叫倒排索引,存儲了詞在文檔中的位置。比如有下麵三個文檔,已經做好了分詞:

doc1: A/BC/D/EF
doc2: BC/D/XY/Z/Z
doc3: BC/E/MN/XY

首先統計這三個文檔中出現的所有的詞,給這些詞編號,並且統計詞頻:

編號 詞頻
A 1 1
BC 2 3
D 3 2
EF 4 1
XY 5 2
Z 6 2
E 7 1
MN 8 1

然後統計這些詞出現在哪些文檔中,以及出現的位置:

詞編號 文檔和位置
1 (doc1,0)
2 (doc1,1),(doc2,0),(doc3,0)
3 (doc1,2),(doc2,1)
4 (doc1,3)
5 (doc2,2),(doc3,3)
6 (doc2,3,4)
7 (doc3,1)
8 (doc3,2)

 這樣反向索引就建立起來了。現在進行檢索,輸入“BDC”。首先對輸入條件進行分詞,得到“BC/D”,分別檢索BC和D的集合,查反向索引:

{doc1, doc2, doc3} AND {doc1, doc2} = {doc1, doc2}

得到搜索結果集合doc1和doc2。

Elasticsearch是一個分散式的全文檢索資料庫,封裝了Lucene的功能,倒排索引的功能是在Lucene中實現的。Lucene的數據目錄中保存的就是倒排索引數據,包括了詞典和文檔數據,壓縮存儲。Lucene的索引是分域存儲的,比純粹的文本索引複雜的多,具體的原理可以看Lucene代碼。

3.排序

把關鍵詞從文檔的海洋中檢索出來只是萬里長征走完了第一步,後面還有一件更重要、難度也更大的事情:排序。對於海量數據來說,排序不合理和檢索不正確造成的後果其實沒有多大的區別(甚至要更嚴重,個人觀點)。

Lucene預設的排序方式是根據關鍵詞文檔相關性,預設的演算法是TF-IDF。TF詞頻(Term Frequency),IDF逆向文件頻率(Inverse Document Frequency)。

具體的公式這裡就不寫了,維基百科上有個例子,https://zh.wikipedia.org/wiki/TF-IDF,這裡說明一下:

首先計算單詞的TF-IDF:假如一篇文件的總詞語數是100個,而詞語“母牛”出現了3次,那麼“母牛”一詞在該文件中的詞頻就是3/100=0.03。一個計算文件頻率(DF)的方法是測定有多少份文件出現過“母牛”一詞,然後除以文件集里包含的文件總數。所以,如果“母牛”一詞在1,000份文件出現過,而文件總數是10,000,000份的話,其逆向文件頻率就是log(10,000,000 / 1,000)=4。最後的TF-IDF的分數為0.03 * 4=0.12。

再計算關鍵詞與文檔的相關性:根據關鍵字k1,k2,k3進行搜索結果的相關性就變成TF1 * IDF1 + TF2 * IDF2 + TF3 * IDF3。比如document1的term總量為1000,k1,k2,k3在document1出現的次數是100,200,50。包含了k1, k2, k3的document總量分別是 1000,10000,5000。document set的總量為10000。 TF1 = 100/1000 = 0.1 TF2 = 200/1000 = 0.2 TF3 = 50/1000 = 0.05 IDF1 = In(10000/1000) = In (10) = 2.3 IDF2 = In(10000/10000) = In (1) = 0; IDF3 = In(10000/5000) = In (2) = 0.69 這樣關鍵字k1,k2,k3與document1的相關性 = 0.1 * 2.3 + 0.2 * 0 + 0.05 * 0.69 = 0.2645 其中k1比k3的比重在document1要大,k2的比重是0.

這是理論上的相關性演算法,實際上可以根據其他因素來修正。比如Google的page rank演算法,會提前根據連接數和引用數算出網頁的page rank得分,計算關鍵詞相關性的時候還會考慮關鍵詞在網頁上出現的位置(title、meta、正文標題、正文內容、側邊欄等等),給出不同的相關度。也可以根據某個業務屬性強制排序(比如create_time等等)。

Elasticsearch是一個分散式的Lucene,排序工作實際上是Lucene做的,Elasticsearch做了一個分步執行、集中排序。

4.檢索方式

4.1 term檢索

term檢索的條件寫法,用SQL表達就是:

SELECT * FROM index/type WHERE status='yes'

term是不分詞檢索,也就是對檢索條件不分詞。所以一般對非文本欄位、不分詞的文本欄位使用這樣的檢索。對分詞文本欄位用term檢索要慎重。比如對這樣的文檔:

fulltext: AB/CD/E/FG

如果用term檢索:

WHERE fulltext='CDE'

由於文檔的fulltext欄位中不存在“CDE”這個詞,所以檢索不到文檔。

4.2 matchQuery檢索

matchQuery條件寫法:

SELECT * FROM index/type WHERE fulltext=matchQuery('ABE')

matchQuery是分詞檢索,先對檢索條件進行分詞,得到“AB/E”,然後尋找fulltext中同時包含“AB”和“E”的文檔。我們對fulltext進行ik max word分詞,matchQuery使用ik smart分詞,這樣能夠最大限度的避免分詞不准確對效果的影響。

4.3 spanNearQuery檢索

spanNearQuery條件寫法:

SELECT * FROM index/type WHERE fulltext=spanNearQuery('ABE')

spanNearQuery是分詞檢索,同時要求條件在文檔中一定要連續出現。所以spanNearQuery要求索引和檢索一定要使用完全相同的分詞策略。比如對“遠郊寄養家庭”,分詞後是“遠郊/郊/寄養/寄/養家/家庭/家/庭”,如果檢索條件是:

WHERE fulltext=spanNearQuery('寄養家庭')

搜索時先對條件使用同樣的分詞策略,然後判斷fulltext中是否連續出現搜索詞。

4.4 query檢索

query條件寫法:

SELECT * FROM index/type WHERE fulltext=query('chin*')

query也是分詞檢索,首先在字典中尋找符合“chin*”通配符的詞,比如“china”、“chinese”等等。然後尋找含有任一詞的文檔。

5.自定義詞典

ik分片語件使用詞典分詞,可以修改詞典定義提高分詞的準確性。

ik組件可以使用自定義詞典,配置文件:/server/elasticsearch/config/ik/IKAnalyzer.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
  <comment>IK Analyzer 擴展配置</comment>
  <!--用戶可以在這裡配置自己的擴展字典 -->
  <entry key="ext_dict">custom/mydict.dic;custom/single_word_low_freq.dic</entry>
  <!--用戶可以在這裡配置自己的擴展停止詞字典-->
  <entry key="ext_stopwords">custom/ext_stopword.dic</entry>
  <!--用戶可以在這裡配置遠程擴展字典 -->
  <entry key="remote_ext_dict">http://localhost/ext_dict.php</entry>
  <!--用戶可以在這裡配置遠程擴展停止詞字典-->
  <entry key="remote_ext_stopwords">http://localhost/ext_stopwords.php</entry>
</properties>

修改本地詞典和停止詞文件,需要在每個Elasticsearch節點上修改文件,修改後重啟。

使用遠程字典可以集中維護字典文件,並且不需要重啟Elasticsearch。ik每分鐘向遠程地址發出請求,請求有一個“If-Modified-Since”消息頭。如果字典沒有變動,返回“304 Not Modified”,ik不會更新字典。如果字典內容有變動,返回字典內容和新的“Last-Modified”,ik更新字典。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 介紹 1.下載解壓 下載地址:http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.14-winx64.zip 將下載的mysql解壓重命名放在C:\Program Files\MySQL\MySQL Server 5.7” 2.創建目錄 創建 ...
  • 在SQL Server中使用OPENROWSET訪問ORACLE資料庫時,你可能會遇到各種坑,下麵一一梳理一下你會遇到的一些坑。 1:資料庫沒有開啟"Ad Hoc Distributed Queries"選項,那麼你就會遇到下麵坑。 SELECT TOP 10 * FROM OPENROWSET('... ...
  • 一、功能介紹 1.MySQL Servers 該功能是mysql主要的服務,也是必須安裝的功能。 2.Mysql WorkBench 這個是mysql的客戶端工具,可以單獨下載安裝程式安裝。 3.Mysql Notifier 該功能可以控制mysql啟動,安裝了該功能會在電腦右下角的圖標中有控制my ...
  • 前幾天在開發一個系統,需要用到隨機字元串,但是mysql的庫函數有沒有直接提供,就簡單的利用現有的函數東拼西湊出隨機字元串來.下麵簡單的說下實現當時. 1.簡單粗暴. 上訴示例產生的是:6位長度的隨機字元串. 函數解釋: rand() :產生 0-1之間的小數,簡稱種子.rand()*25 產生的數 ...
  • MySQL binlog記錄的所有操作實際上都有對應的事件類型的,譬如STATEMENT格式中的DML操作對應的是QUERY_EVENT類型,ROW格式下的DML操作對應的是ROWS_EVENT類型。 首先,看看源碼中定義的事件類型 源碼位置:mysql-5.7.14/libbinlogevents ...
  • 在老系統中該函數調用一次需要話20多秒到30秒左右。 拿到sql之後,首先要確定思路。不能著急這下手。 1. 首先查看各個表的數據量: select count(*) from xxx; 發現只有 a21 的數據量達到了十幾萬,其他表數據量都比較小。所以重點是 a21表,仔細閱讀了一遍函數的定義,發 ...
  • 在SQL Server中,在鏈接伺服器中調用表值函數(table-valued function)時,會遇到下麵錯誤: SELECT * FROM LNK_TEST.TEST.DBO.TEST(12) 消息 4122,級別 16,狀態 1,第 1 行 Remote table-valued func... ...
  • SQL Server 的事務日誌包含所有數據修改的操作記錄。分析日誌一般作為解決某些問題的最後手段,如查看某些意外的修改。理解和分析日誌內容是件非常困難的事情,fn_dblog通常會輸出非常多的數據,查看也比較困難。我嘗試用一些實例幫助大家更好地分析和理解日誌。 SQL Server 使用Write ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...