分析器(Analyzer)的執(zhí)行過程
如下圖是語匯單元的生成過程:

從一個Reader字符流開始,創(chuàng)建一個基于Reader的Tokenizer分詞器,經(jīng)過三個TokenFilter生成語匯單元Token。
要看分析器的分析效果,只需要看Tokenstream中的內(nèi)容就可以了。每個分析器都有一個方法tokenStream,返回一個tokenStream對象。
Lucene自帶中文分析器
- StandardAnalyzer:
??單字分詞:就是按照中文一個字一個字地進(jìn)行分詞。如:“我愛中國”,
??效果:“我”、“愛”、“中”、“國”。 - CJKAnalyzer
??二分法分詞:按兩個字進(jìn)行切分。如:“我是中國人”,效果:“我是”、“是中”、“中國”“國人”。
上邊兩個分詞器無法滿足需求。
- SmartChineseAnalyzer
??對中文支持較好,但擴(kuò)展性差,擴(kuò)展詞庫,禁用詞庫和同義詞庫等不好處理
第三方中文分詞器
paoding: 庖丁解牛最新版在 https://code.google.com/p/paoding/ 中最多支持Lucene 3.0,且最新提交的代碼在 2008-06-03,在svn中最新也是2010年提交,已經(jīng)過時,不予考慮。
mmseg4j:最新版已從https://code.google.com/p/mmseg4j/ 移至https://github.com/chenlb/mmseg4j-solr,支持Lucene 4.10,且在github中最新提交代碼是2014年6月,從09年~14年一共有:18個版本,也就是一年幾乎有3個大小版本,有較大的活躍度,用了mmseg算法。
IK-analyzer: 最新版在https://code.google.com/p/ik-analyzer/上,支持Lucene 4.10從2006年12月推出1.0版開始, IKAnalyzer已經(jīng)推出了4個大版本。最初,它是以開源項(xiàng)目Luence為應(yīng)用主體的,結(jié)合詞典分詞和文法分析算法的中文分詞組件。從3.0版本開 始,IK發(fā)展為面向Java的公用分詞組件,獨(dú)立于Lucene項(xiàng)目,同時提供了對Lucene的默認(rèn)優(yōu)化實(shí)現(xiàn)。在2012版本中,IK實(shí)現(xiàn)了簡單的分詞 歧義排除算法,標(biāo)志著IK分詞器從單純的詞典分詞向模擬語義分詞衍化。 但是也就是2012年12月后沒有在更新。
ansj_seg:最新版本在 https://github.com/NLPchina/ansj_seg , tags僅有1.1版本,從2012年到2014年更新了大小6次,但是作者本人在2014年10月10日說明:“可能我以后沒有精力來維護(hù)ansj_seg了”,現(xiàn)在由”nlp_china”管理。2014年11月有更新。并未說明是否支持Lucene,是一個由CRF(條件隨機(jī)場)算法所做的分詞算法。
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算法。
使用IK
使用方法:
-
第一步:把jar包添加到工程中
-
第二步:把配置文件和擴(kuò)展詞典和停用詞詞典添加到classpath下
config為src目錄

-
IKAnalyzer.cfg.xml如下:
<?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">ext.dic;</entry>
<!--用戶可以在這里配置自己的擴(kuò)展停止詞字典-->
<entry key="ext_stopwords">stopword.dic;</entry>
</properties>
注意:mydict.dic和ext_stopword.dic文件的格式為UTF-8,注意是無BOM 的UTF-8 編碼。
- 將生成索引的分詞器修改為
IKAnalyzer()
package cn.huahcao.lucene;
import org.apache.commons.io.FileUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.LongField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;
import org.wltea.analyzer.lucene.IKAnalyzer;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class IndexManagerTest {
@Test
public void testCreateIndex() throws Exception{
//采集文件系統(tǒng)中的文檔數(shù)據(jù),放入lucene中
//文檔列表,保存Document
List<Document> docList = new ArrayList<Document>();
//指定文件所在的目錄
File dir = new File("G:\\Java\\JavaEE\\09_SSM\\lucene_day01\\參考資料\\searchsource");
//循環(huán)取出文件
for (File file:dir.listFiles()){
//文件名稱
String fileName = file.getName();
//文件內(nèi)容
String fileContext = FileUtils.readFileToString(file);
//文件大小
Long fileSize = FileUtils.sizeOf(file);
//文檔對象。文件系統(tǒng)中的一個文件就是一個Document對象
Document doc = new Document();
/**
* 第一個參數(shù):域名
* 第二個參數(shù):域值
* 第三個參數(shù):是否存儲,是為Yes,不存儲為No
*/
// TextField nameFiled = new TextField("fileName",fileName, Field.Store.YES);
// TextField contextFiled = new TextField("fileContent",fileContent, Field.Store.YES);
// TextField sizeFiled = new TextField("fileSize",fileSize.toString(), Field.Store.YES);
//是否分詞:要,因?yàn)樗饕?并且它不是一個整體,分詞有意義
//是否索引:要,因?yàn)橐ㄟ^它來進(jìn)行搜索
//是否存儲:要,因?yàn)橐苯釉陧撁嫔巷@示
TextField nameFiled = new TextField("fileName", fileName, Field.Store.YES);
//是否分詞: 要,因?yàn)橐鶕?jù)內(nèi)容進(jìn)行搜索,并且它分詞有意義
//是否索引: 要,因?yàn)橐鶕?jù)它進(jìn)行搜索
//是否存儲: 可以要也可以不要,不存儲搜索完內(nèi)容就提取不出來
TextField contextFiled = new TextField("fileContext", fileContext, Field.Store.NO);
//是否分詞: 要, 因?yàn)閿?shù)字要對比,搜索文檔的時候可以搜大小, lunene內(nèi)部對數(shù)字進(jìn)行了分詞算法
//是否索引: 要, 因?yàn)橐鶕?jù)大小進(jìn)行搜索
//是否存儲: 要, 因?yàn)橐@示文檔大小
LongField sizeFiled = new LongField("fileSize", fileSize, Field.Store.YES);
//將所有的域存入文檔中
doc.add(nameFiled);
doc.add(contextFiled);
doc.add(sizeFiled);
//將文檔存入文檔集合中
docList.add(doc);
}
//創(chuàng)建分詞器,StandardAnalyzer標(biāo)準(zhǔn)分詞器,標(biāo)準(zhǔn)分詞器對英文分詞效果很好,對中文是單字分詞
Analyzer analyzer = new IKAnalyzer();
//指定索引和文檔存儲的目錄
FSDirectory directory = FSDirectory.open(new File("G:\\Java\\JavaEE\\09_SSM\\lucene_day01\\tmp"));
//創(chuàng)建寫對象的初始化對象
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3,analyzer);
//創(chuàng)建索引和文檔寫對象
IndexWriter indexWriter = new IndexWriter(directory , config);
//將文檔加入到索引和文檔的寫對象中
for (Document doc:docList){
indexWriter.addDocument(doc);
}
//提交
indexWriter.commit();
//關(guān)閉流
indexWriter.close();
}
}
-
執(zhí)行上面的testCreateIndex()
-
用luke查看
從上面可以看出中文是按詞義分的,而不是之前的一個字一個字的分



