一、相關(guān)度排序
1.什么是相關(guān)度排序
相關(guān)度排序是查詢結(jié)果按照與查詢關(guān)鍵字的相關(guān)性進(jìn)行排序,越相關(guān)的越靠前。比如搜索“Lucene”關(guān)鍵字,與該關(guān)鍵字最相關(guān)的文章應(yīng)該排在前邊。
2.相關(guān)度打分
Lucene對(duì)查詢關(guān)鍵字和索引文檔的相關(guān)度進(jìn)行打分,得分高的就排在前邊。如何打分呢?Lucene是在用戶進(jìn)行檢索時(shí)實(shí)時(shí)根據(jù)搜索的關(guān)鍵字計(jì)算出來(lái)的,分兩步:
- 計(jì)算出詞(Term)的權(quán)重
- 根據(jù)詞的權(quán)重值,計(jì)算文檔相關(guān)度得分。
什么是詞的權(quán)重?
明確索引的最小單位是一個(gè)Term(索引詞典中的一個(gè)詞),搜索也是要從Term中搜索,再根據(jù)Term找到文檔,Term對(duì)文檔的重要性稱為權(quán)重,影響Term權(quán)重有兩個(gè)因素:
Term Frequency (tf):
指此Term在此文檔中出現(xiàn)了多少次。tf 越大說(shuō)明越重要。 詞(Term)在文檔中出現(xiàn)的次數(shù)越多,說(shuō)明此詞(Term)對(duì)該文檔越重要,如“Lucene”這個(gè)詞,在文檔中出現(xiàn)的次數(shù)很多,說(shuō)明該文檔主要就是講Lucene技術(shù)的。Document Frequency (df):
指有多少文檔包含次Term。df 越大說(shuō)明越不重要。
比如,在一篇英語(yǔ)文檔中,this出現(xiàn)的次數(shù)更多,就說(shuō)明越重要嗎?不是的,有越多的文檔包含此詞(Term), 說(shuō)明此詞(Term)太普通,不足以區(qū)分這些文檔,因而重要性越低。
3.設(shè)置boost值影響相關(guān)度排序
boost是一個(gè)加權(quán)值(默認(rèn)加權(quán)值為1.0f),它可以影響權(quán)重的計(jì)算。
- 在索引時(shí)對(duì)某個(gè)文檔中的field設(shè)置加權(quán)值高,在搜索時(shí)匹配到這個(gè)文檔就可能排在前邊。
- 在搜索時(shí)對(duì)某個(gè)域進(jìn)行加權(quán),在進(jìn)行組合域查詢時(shí),匹配到加權(quán)值高的域最后計(jì)算的相關(guān)度得分就高。
設(shè)置boost是給域(field)或者Document設(shè)置的。
3.1 在創(chuàng)建索引時(shí)設(shè)置
如果希望某些文檔更重要,當(dāng)此文檔中包含所要查詢的詞則應(yīng)該得分較高,這樣相關(guān)度排序可以排在前邊,可以在創(chuàng)建索引時(shí)設(shè)定文檔中某些域(Field)的boost值來(lái)實(shí)現(xiàn),如果不進(jìn)行設(shè)定,則Field Boost默認(rèn)為1.0f。一旦設(shè)定,除非刪除此文檔,否則無(wú)法改變。
@Test
public void setBoost4createIndex() throws Exception {
// 創(chuàng)建分詞器
Analyzer analyzer = new StandardAnalyzer();
IndexWriterConfig cfg = new IndexWriterConfig(Version.LUCENE_4_10_3,
analyzer);
Directory directory = FSDirectory.open(new File("E:\\11-index\\0728"));
// 創(chuàng)建IndexWriter對(duì)象,通過(guò)它把分好的詞寫(xiě)到索引庫(kù)中
IndexWriter writer = new IndexWriter(directory, cfg);
Document doc = new Document();
Field id = new StringField("id", "11", Store.YES);
Field description = new TextField("description", "測(cè)試設(shè)置BOOST值 lucene",
Store.YES);
// 設(shè)置boost
description.setBoost(10.0f);
// 把域添加到文檔中
doc.add(id);
doc.add(description);
writer.addDocument(doc);
// 關(guān)閉IndexWriter
writer.close();
}
輸出:

3.2 在查詢索引時(shí)設(shè)置
在MultiFieldQueryParser創(chuàng)建時(shí)設(shè)置boost值。
@Test
public void multiFieldQueryParser() throws Exception {
// 創(chuàng)建7.3.2 MultiFieldQueryParser
// 默認(rèn)搜索的多個(gè)域的域名
String[] fields = { "name", "description" };
Analyzer analyzer = new StandardAnalyzer();
Map<String, Float> boosts = new HashMap<String, Float>();
boosts.put("name", 200f);
MultiFieldQueryParser parser = new MultiFieldQueryParser(fields,
analyzer, boosts);
// Query query = parser.parse("name:lucene OR description:lucene");
//等同于name:lucene OR description:lucene
Query query = parser.parse("java");
System.out.println(query);
doSearch(query);
}
二、中文分詞器
1.什么是中文分詞器
英文是以單詞為單位的,單詞與單詞之間以空格或者逗號(hào)句號(hào)隔開(kāi)。而中文則以字為單位,字又組成詞,字和詞再組成句子。所以對(duì)于英文,我們可以簡(jiǎn)單以空格判斷某個(gè)字符串是否為一個(gè)單詞,比如I love China,love 和 China很容易被程序區(qū)分開(kāi)來(lái);但中文“我愛(ài)中國(guó)”就不一樣了,電腦不知道“中國(guó)”是一個(gè)詞語(yǔ)還是“愛(ài)中”是一個(gè)詞語(yǔ)。把中文的句子切分成有意義的詞,就是中文分詞,也稱切詞。我愛(ài)中國(guó),分詞的結(jié)果是:我 愛(ài) 中國(guó)。
2.Lucene自帶的中文分詞器
StandardAnalyzer:
單字分詞:就是按照中文一個(gè)字一個(gè)字地進(jìn)行分詞。如:“我愛(ài)中國(guó)”,
效果:“我”、“愛(ài)”、“中”、“國(guó)”。CJKAnalyzer:
二分法分詞:按兩個(gè)字進(jìn)行切分。如:“我是中國(guó)人”,效果:“我是”、“是中”、“中國(guó)”“國(guó)人”。
上邊兩個(gè)分詞器無(wú)法滿足需求。
3.第三方中文分詞器
paoding: 庖丁解牛最新版在 https://code.google.com/p/paoding/ 中最多支持Lucene 3.0,且最新提交的代碼在 2008-06-03,在svn中最新也是2010年提交,已經(jīng)過(guò)時(shí),不予考慮。
mmseg4j:最新版已從 https://code.google.com/p/mmseg4j/ 移至 https://github.com/chenlb/mmseg4j-solr,支持Lucene 4.10,且在github中最新提交代碼是2014年6月,從09年~14年一共有:18個(gè)版本,也就是一年幾乎有3個(gè)大小版本,有較大的活躍度,用了mmseg算法。
IK-analyzer: 最新版在https://code.google.com/p/ik-analyzer/上,支持Lucene 4.10從2006年12月推出1.0版開(kāi)始, IKAnalyzer已經(jīng)推出了4個(gè)大版本。最初,它是以開(kāi)源項(xiàng)目Luence為應(yīng)用主體的,結(jié)合詞典分詞和文法分析算法的中文分詞組件。從3.0版本開(kāi) 始,IK發(fā)展為面向Java的公用分詞組件,獨(dú)立于Lucene項(xiàng)目,同時(shí)提供了對(duì)Lucene的默認(rèn)優(yōu)化實(shí)現(xiàn)。在2012版本中,IK實(shí)現(xiàn)了簡(jiǎn)單的分詞 歧義排除算法,標(biāo)志著IK分詞器從單純的詞典分詞向模擬語(yǔ)義分詞衍化。 但是也就是2012年12月后沒(méi)有在更新。
ansj_seg:最新版本在 https://github.com/NLPchina/ansj_seg tags僅有1.1版本,從2012年到2014年更新了大小6次,但是作者本人在2014年10月10日說(shuō)明:“可能我以后沒(méi)有精力來(lái)維護(hù)ansj_seg了”,現(xiàn)在由”nlp_china”管理。2014年11月有更新。并未說(shuō)明是否支持Lucene,是一個(gè)由CRF(條件隨機(jī)場(chǎng))算法所做的分詞算法。
imdict-chinese-analyzer:最新版在 https://code.google.com/p/imdict-chinese-analyzer/ , 最新更新也在2009年5月,下載源碼,不支持Lucene 4.10 。是利用HMM(隱馬爾科夫鏈)算法。
Jcseg:最新版本在git.oschina.net/lionsoul/jcseg,支持Lucene 4.10,作者有較高的活躍度。利用mmseg算法。
4.使用中文分詞器IKAnalyzer

IKAnalyzer繼承Lucene的Analyzer抽象類,使用IKAnalyzer和Lucene自帶的分析器方法一樣,將Analyzer測(cè)試代碼改為IKAnalyzer測(cè)試中文分詞效果。
如果使用中文分詞器ik-analyzer,就在索引和搜索程序中使用一致的分詞器ik-analyzer。
4.1添加jar包

4.2 修改分詞器代碼
// 創(chuàng)建分詞器,標(biāo)準(zhǔn)分詞器
// Analyzer analyzer = new StandardAnalyzer();
// 使用ikanalyzer
Analyzer analyzer = new IKAnalyzer();
5.擴(kuò)展中文詞庫(kù)
將以下文件拷貝到config目錄下

從ikanalyzer包中拷貝配置文件到classpath下。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 擴(kuò)展配置</comment>
<!-- 用戶可以在這里配置自己的擴(kuò)展字典 -->
<entry key="ext_dict">dicdata/mydict.dic</entry>
<!-- 用戶可以在這里配置自己的擴(kuò)展停用詞字典 -->
<entry key="ext_stopwords">dicdata/ext_stopword.dic</entry>
</properties>
如果想配置擴(kuò)展詞和停用詞,就創(chuàng)建擴(kuò)展詞的文件和停用詞的文件,文件的編碼要是utf-8。
注意:不要用記事本保存擴(kuò)展詞文件和停用詞文件,那樣的話,格式中是含有bom的。
添加擴(kuò)展詞文件:ext.dic,內(nèi)容:我愛(ài)中國(guó)
6.使用luke測(cè)試中文分詞
第一步:將ikanalyzer的jar包,拷貝到luke工具的目錄

使用Luke測(cè)試第三方分詞器分詞效果,需通過(guò)java.ext.dirs加載jar包:
可簡(jiǎn)單的將第三方分詞器和lukeall放在一塊兒,cmd下運(yùn)行:

第二步:使用命令打開(kāi)luke工具:
java -Djava.ext.dirs=. -jar lukeall-4.10.3.jar
