在中文搜索中,分詞技術是一個比較關鍵的技術,我們往往會遇到查詢某個關鍵字無法匹配到相應文檔的問題,這種問題往往都是索引的分詞不理想造成的,倒排索引的技術特點決定了如果查詢的關鍵字不在索引的分詞中,則無法查出相應的文檔。為了幫助使用者分析分詞問題,hubbledotnet 專門提供幾個存儲過程來幫助檢查索引分詞的情況。
分詞的測試方法
首先要找到要測試的原始文本
我們往往發現某些記錄包含有查詢關鍵字,但查不出來,這個時候我們需要先找到這個出問題的記錄的原始文本。查找原始文本的方法很多,你可以通過 docid 或者id 或者其他條件來查找。
下面給出一個通過 id 來查找的示例。如果我們發現id = 1 的記錄 title 無法匹配出來,我們可以執行
select * from table where id = 1 找到記錄的原始文本。
找到原始文本后我們有兩種方法來查看記錄在索引中的分詞情況。
方法1: SP_TestAnalyzer
SP_TestAnalyzer 這個存儲過程用於測試分詞器的分詞結果,它的作用是在服務器側執行分詞器的 Tokenize 方法。
這個存儲過程有兩個參數,第一個參數為分詞器名字,這里我們輸入 ‘PanguSegment’,第二個參數是要測試的句子。
下面我們執行如下語句,看看效果
SP_TestAnalyzer 'PanguSegment', '六方會談無核化工作組會議將在沈陽召開'
如上圖所示,執行后,可以看到分詞的結果。從這個分詞結果可以看到原始文本的分詞有一些問題,比如無核化和工作組這兩個詞沒有分出來,這時如果搜索”工作組”這個詞,則無法匹配到這條記錄。我們需要把無核化和工作組兩個詞加入到盤古的字典中再測試,如果分詞正確了,重新索引后,問題就可以解決。
方法2:SP_FieldAnalyze
SP_FieldAnalyze 這個存儲過程是針對指定表的指定字段的分詞器來分詞
它有4個參數,參數1為表名,參數2為字段名,參數3為要分詞的句子,參數4指定是用 Tokenize 函數還是 TokenizedForSqlClient 函數來分詞。第4個參數為可選參數,
如果不輸入,就是以 Tokenize 函數分詞,如果輸入 ‘SqlClient’ 就是以 TokenizedForSqlClient 函數來分詞
下面我們首先執行默認的情況,即用 Tokenize 函數分詞
SP_FieldAnalyze 'VNews', 'Title', '六方會談無核化工作組會議將在沈陽召開'
這個語句是采用 VNews 表的 Title 字段的分詞器來對 '六方會談無核化工作組會議將在沈陽召開' 這個句子進行分詞,我們可以看出,分詞的結果和方法1是一樣的。
我們加上 SqlClient 參數后來分詞看看效果:
SP_FieldAnalyze 'VNews', 'Title', '六方會談無核化工作組會議將在沈陽召開','SqlClient'
可以看到后面加了 SqlClient 后,分詞結果不同了,這是因為 SqlClient 采用了不同的分詞參數。對於盤古分詞來說,如果調用 SqlClient 來分詞,則服務器側調用的是program/hubbledotnet/default/PanGuSqlClient.xml 這個配置文件來對文本進行分詞,如果不加 SqlClient 參數,則是調用program/hubbledotnet/default/PanGu.xml 這個配置文件分詞。
SqlClient 的功能主要是幫助進行查詢字符串的分詞,HubbleCommand 這個類中有一個函數 GetKeywordAnalyzerStringFromServer 就是用於對查詢字符串進行分詞的,hubble 的示例代碼中也是調用的這個函數,這個函數的里面實際上就是調用 SP_FieldAnalyze 這個存儲過程加 SqlClient 來分詞。當然在實際項目中,使用着並不是必須要調用這個函數來對查詢字符串進行分詞,使用者可以用自己的程序對查詢字符串分詞。
分詞的技巧
對於搜索來說,查全率和查准率是一對矛盾,為了盡量平衡這對矛盾,我們在索引和查詢時可以采用一些技巧。
技巧1.
索引時最大化分詞,如果是用盤古分詞進行索引,索引時打開多元分詞和強制一元分詞。但對查詢字符串的分詞則采用精確分詞,這樣可以保證查准的情況下獲得較大的查全率。
技巧2.
同義詞分詞。對於同義詞的分詞,我們不要在索引中分詞,而是在查詢字符串中增加同義詞的分解,這樣可以使查詢更靈活,並且可以在查詢時設置原詞和同義詞不同的權重以影響得分排名。
技巧3.
全部一元分詞,然后通過索引組件來實現匹配,類似 like ‘%xxx%’ 這樣的功能。由於索引組件知道單詞在原文本中的位置,所以理論上可以實現類似 like ‘%xxx%’ 這樣的功能,這種功能對於短文本的搜索比較有效,而且不需要關心中文的分詞。hubbledotnet 將在未來的版本中提供這種方式的快速解決方案,目前版本提供了 like ‘*xxx*’ 的功能,但這個功能還不夠完善,速度比較慢。
注意事項
索引分詞的檢查功能,實際上只是在server 端執行了對應的分詞器來進行分詞,並不是從倒排索引中查詢出對應文本的分詞結果。從倒排索引中獲取分詞結果需要遍歷整個倒排索引,效率很低,所以hubble 沒有提供這樣的功能。由於是動態執行分詞器分詞,如果在索引過程中分詞參數或字典調整過,則得到的結果有可能不是實際索引中的分詞結果。