1. Analyzer
Lucene内置分词器SimpleAnalyzer、StopAnalyzer、WhitespaceAnalyzer、StandardAnalyzer
主要作用:
KeywordAnalyzer分词,没有任何变化;
SimpleAnalyzer对中文效果太差;
StandardAnalyzer对中文单字拆分;
StopAnalyzer和SimpleAnalyzer差不多;
WhitespaceAnalyzer只按空格划分。
2. TokenStream
分词器做好处理之后得到的一个流,这个流中存储了分词的各种信息,可以通过TokenStream有效的获取到分词单元信息
生成的流程
<a href="http://s3.51cto.com/wyfs02/M02/49/04/wKiom1QNXCjRDia8AAC0d1oqgS8802.jpg" target="_blank"></a>
在这个流中所需要存储的数据
<a href="http://s3.51cto.com/wyfs02/M00/49/05/wKioL1QNXD_D-wnJAADBZV4ljMM627.jpg" target="_blank"></a>
3. Tokenizer
主要负责接收字符流Reader,将Reader进行分词操作。有如下一些实现类
<a href="http://s3.51cto.com/wyfs02/M00/49/04/wKiom1QNXGHBgyjGAAFfL_LVWgc751.jpg" target="_blank"></a>
4. TokenFilter
将分词的语汇单元,进行各种各样过滤
<a href="http://s3.51cto.com/wyfs02/M01/49/05/wKioL1QNXH7Rb2ESAADkQpvbtrs160.jpg" target="_blank"></a>
5.扩展:TokenFilter各类介绍:
(1),TokenFilter
输入参数为另一个TokerStream的TokerStream,其子类必须覆盖incrementToken()函数。
(2),LowerCaseFilter
将Token分词转换为小写。
(3),FilteringTokenFilter
TokenFilters的一个抽象类,可能会删除分词。如果当前分词要保存,则需要实现accept()方法
并返回一个boolean值。incrementToken()方法将调用accept()方法来决定是否将当前的分词返回
给调用者。
(4),StopFilter
从token stream中移除停止词(stop words).
<code>protected</code> <code>boolean</code> <code>accept() {</code>
<code> </code><code>return</code><code>!stopWords.contains(termAtt.buffer(), </code><code>0</code><code>, termAtt.length());</code><code>//返回不是stop word的分词</code>
<code> </code><code>}</code>
(5),TypeTokenFilter
从token stream中移除指定类型的分词。
<code> </code><code>returnuseWhiteList == stopTypes.contains(typeAttribute.type());</code>
<code>}</code>
(6),LetterTokenizer
是一个编译器,将文本在非字母。说,它定义了令牌的最大字符串相邻的字母
(7),TokenFilter的顺序问题
此时停止词 the 就未被去除了。先全部转换为小写字母,再过滤停止词(The 转换成 the 才可以与停止词词组里的 the 匹配),如果不限制大小写,停止词的组合就太多了。
<code>import</code> <code>java.io.Reader;</code>
<code>import</code> <code>java.util.Set;</code>
<code>import</code> <code>org.apache.lucene.analysis.Analyzer;</code>
<code>importorg.apache.lucene.analysis.LetterTokenizer;</code>
<code>importorg.apache.lucene.analysis.LowerCaseFilter;</code>
<code>import</code> <code>org.apache.lucene.analysis.StopAnalyzer;</code>
<code>import</code> <code>org.apache.lucene.analysis.StopFilter;</code>
<code>import</code> <code>org.apache.lucene.analysis.TokenStream;</code>
<code>import</code> <code>org.apache.lucene.util.Version;</code>
<code>public</code> <code>class</code> <code>MyStopAnalyzer </code><code>extends</code> <code>Analyzer {</code>
<code> </code><code>privateSet<Object> words;</code>
<code> </code><code>publicMyStopAnalyzer(){}</code>
<code> </code><code>publicMyStopAnalyzer(String[] words ){</code>
<code> </code><code>this</code><code>.words=StopFilter.makeStopSet(Version.LUCENE_35,words, </code><code>true</code><code>);</code>
<code> </code><code>this</code><code>.words.addAll(StopAnalyzer.ENGLISH_STOP_WORDS_SET)</code>
<code> </code><code>}</code>
<code> </code>
<code> </code><code>@Override</code>
<code> </code><code>publicTokenStream tokenStream(String fieldName, Reader reader) {</code>
<code> </code><code>// TODO Auto-generatedmethod stub</code>
<code> </code><code>return</code> <code>newStopFilter(Version.LUCENE_35,</code><code>new</code> <code>LowerCaseFilter(Version.LUCENE_35, newLetterTokenizer(Version.LUCENE_35,reader)),</code><code>this</code><code>.words);</code>
<code>public</code> <code>static</code> <code>void</code> <code>displayAllTokenInfo(Stringstr,Analyzer a) {</code>
<code> </code><code>try</code><code>{</code>
<code> </code><code>TokenStreamstream = a.tokenStream(</code><code>"content"</code><code>,</code><code>new</code> <code>StringReader(str));</code>
<code> </code><code>//位置增量的属性,存储语汇单元之间的距离</code>
<code> </code><code>PositionIncrementAttributepia = </code>
<code> </code><code>stream.addAttribute(PositionIncrementAttribute.</code><code>class</code><code>);</code>
<code> </code><code>//每个语汇单元的位置偏移量</code>
<code> </code><code>OffsetAttributeoa = </code>
<code> </code><code>stream.addAttribute(OffsetAttribute.</code><code>class</code><code>);</code>
<code> </code><code>//存储每一个语汇单元的信息(分词单元信息)</code>
<code> </code><code>CharTermAttributecta = </code>
<code> </code><code>stream.addAttribute(CharTermAttribute.</code><code>class</code><code>);</code>
<code> </code><code>//使用的分词器的类型信息</code>
<code> </code><code>TypeAttributeta = </code>
<code> </code><code>stream.addAttribute(TypeAttribute.</code><code>class</code><code>);</code>
<code> </code><code>for</code><code>(;stream.incrementToken();){</code>
<code> </code><code>System.out.print(pia.getPositionIncrement()+</code><code>":"</code><code>);</code>
<code> </code><code>System.out.print(cta+</code><code>"["</code><code>+oa.startOffset()+</code><code>"-"</code><code>+oa.endOffset()+</code><code>"]-->"</code><code>+ta.type()+</code><code>"\n"</code><code>);</code>
<code> </code><code>}</code>
<code> </code><code>}</code><code>catch</code> <code>(Exception e) {</code>
<code> </code><code>e.printStackTrace();</code>
<code> </code><code>}</code>
<code> </code><code>}</code>
1.自定义Stop分词器
<code>package</code> <code>com.mzsx.analyzer;</code>
<code> </code><code>privateSet<Object> words;</code>
<code> </code><code>publicMyStopAnalyzer(){}</code>
<code> </code><code>publicMyStopAnalyzer(String[] words ){</code>
<code> </code><code>this</code><code>.words=StopFilter.makeStopSet(Version.LUCENE_35,words, </code><code>true</code><code>);</code>
<code> </code><code>this</code><code>.words.addAll(StopAnalyzer.ENGLISH_STOP_WORDS_SET);</code>
<code> </code>
<code> </code><code>@Override</code>
<code> </code><code>publicTokenStream tokenStream(String fieldName, Reader reader) {</code>
<code> </code><code>returnnew StopFilter(Version.LUCENE_35,</code><code>new</code> <code>LowerCaseFilter(Version.LUCENE_35, newLetterTokenizer(Version.LUCENE_35,reader)),</code><code>this</code><code>.words);</code>
<code>//测试代码</code>
<code>@Test</code>
<code> </code><code>publicvoid myStopAnalyzer() {</code>
<code> </code><code>Analyzera1 = </code><code>new</code> <code>MyStopAnalyzer(</code><code>new</code> <code>String[]{</code><code>"I"</code><code>,</code><code>"you"</code><code>,</code><code>"hate"</code><code>});</code>
<code> </code><code>Analyzera2 = </code><code>new</code> <code>MyStopAnalyzer();</code>
<code> </code><code>Stringtxt = </code><code>"how are you thank you I hate you"</code><code>;</code>
<code> </code><code>AnalyzerUtils.displayAllTokenInfo(txt,a1);</code>
<code> </code><code>//AnalyzerUtils.displayToken(txt,a2);</code>
2.简单实现同义词索引
<code>public</code> <code>interface</code> <code>SamewordContext {</code>
<code> </code><code>publicString[] getSamewords(String name);</code>
<code>import</code> <code>java.util.HashMap;</code>
<code>import</code> <code>java.util.Map;</code>
<code>public</code> <code>class</code> <code>SimpleSamewordContext implementsSamewordContext {</code>
<code> </code>
<code> </code><code>Map<String,String[]>maps = </code><code>new</code> <code>HashMap<String,String[]>();</code>
<code> </code><code>publicSimpleSamewordContext() {</code>
<code> </code><code>maps.put(</code><code>"中国"</code><code>,</code><code>new</code> <code>String[]{</code><code>"天朝"</code><code>,</code><code>"大陆"</code><code>});</code>
<code> </code><code>maps.put(</code><code>"我"</code><code>,</code><code>new</code> <code>String[]{</code><code>"咱"</code><code>,</code><code>"俺"</code><code>});</code>
<code> </code><code>maps.put(</code><code>"china"</code><code>,</code><code>new</code> <code>String[]{</code><code>"chinese"</code><code>});</code>
<code> </code><code>publicString[] getSamewords(String name) {</code>
<code> </code><code>returnmaps.get(name);</code>
<code>import</code> <code>java.io.IOException;</code>
<code>import</code> <code>java.util.Stack;</code>
<code>import</code> <code>org.apache.lucene.analysis.TokenFilter;</code>
<code>importorg.apache.lucene.analysis.tokenattributes.CharTermAttribute;</code>
<code>importorg.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;</code>
<code>import</code> <code>org.apache.lucene.util.AttributeSource;</code>
<code>public</code> <code>class</code> <code>MySameTokenFilter extendsTokenFilter {</code>
<code> </code><code>privateCharTermAttribute cta = </code><code>null</code><code>;</code>
<code> </code><code>privatePositionIncrementAttribute pia = </code><code>null</code><code>;</code>
<code> </code><code>privateAttributeSource.State current;</code>
<code> </code><code>privateStack<String> sames = </code><code>null</code><code>;</code>
<code> </code><code>privateSamewordContext samewordContext;</code>
<code> </code><code>protectedMySameTokenFilter(TokenStream input,SamewordContext samewordContext) {</code>
<code> </code><code>super</code><code>(input);</code>
<code> </code><code>cta= </code><code>this</code><code>.addAttribute(CharTermAttribute.</code><code>class</code><code>);</code>
<code> </code><code>pia= </code><code>this</code><code>.addAttribute(PositionIncrementAttribute.</code><code>class</code><code>);</code>
<code> </code><code>sames= </code><code>new</code> <code>Stack<String>();</code>
<code> </code><code>this</code><code>.samewordContext= samewordContext;</code>
<code> </code><code>publicboolean incrementToken() </code><code>throws</code> <code>IOException {</code>
<code> </code><code>if</code><code>(sames.size()></code><code>0</code><code>){</code>
<code> </code><code>//将元素出栈,并且获取这个同义词</code>
<code> </code><code>Stringstr = sames.pop();</code>
<code> </code><code>//还原状态</code>
<code> </code><code>restoreState(current);</code>
<code> </code><code>cta.setEmpty();</code>
<code> </code><code>cta.append(str);</code>
<code> </code><code>//设置位置0</code>
<code> </code><code>pia.setPositionIncrement(</code><code>0</code><code>);</code>
<code> </code><code>returntrue;</code>
<code> </code><code>if</code><code>(!</code><code>this</code><code>.input.incrementToken())</code><code>return</code> <code>false</code><code>;</code>
<code> </code><code>if</code><code>(addSames(cta.toString())){</code>
<code> </code><code>//如果有同义词将当前状态先保存</code>
<code> </code><code>current= captureState();</code>
<code> </code><code>returntrue;</code>
<code> </code><code>privateboolean addSames(String name) {</code>
<code> </code><code>String[]sws = samewordContext.getSamewords(name);</code>
<code> </code><code>if</code><code>(sws!=</code><code>null</code><code>){</code>
<code> </code><code>for</code><code>(Stringstr:sws) {</code>
<code> </code><code>sames.push(str);</code>
<code> </code><code>returnfalse;</code>
<code>import</code> <code>com.chenlb.mmseg4j.Dictionary;</code>
<code>import</code> <code>com.chenlb.mmseg4j.MaxWordSeg;</code>
<code>importcom.chenlb.mmseg4j.analysis.MMSegTokenizer;</code>
<code>public</code> <code>class</code> <code>MySameAnalyzer </code><code>extends</code> <code>Analyzer {</code>
<code> </code><code>publicMySameAnalyzer(SamewordContext swc) {</code>
<code> </code><code>samewordContext= swc;</code>
<code> </code><code>Dictionarydic = Dictionary.getInstance(</code><code>"D:/luceneIndex/dic"</code><code>);</code>
<code> </code><code>returnnew MySameTokenFilter(</code>
<code> </code><code>newMMSegTokenizer(</code><code>new</code> <code>MaxWordSeg(dic), reader),samewordContext);</code>
<code> </code><code>publicvoid testSameAnalyzer() {</code>
<code> </code><code>Analyzera2 = </code><code>new</code> <code>MySameAnalyzer(</code><code>new</code> <code>SimpleSamewordContext());</code>
<code> </code><code>Stringtxt = </code><code>"我来自中国海南儋州第一中学,welcome to china !"</code><code>;</code>
<code> </code><code>Directorydir = </code><code>new</code> <code>RAMDirectory();</code>
<code> </code><code>IndexWriterwriter = </code><code>new</code> <code>IndexWriter(dir,</code><code>new</code> <code>IndexWriterConfig(Version.LUCENE_35, a2));</code>
<code> </code><code>Documentdoc = </code><code>new</code> <code>Document();</code>
<code> </code><code>doc.add(newField(</code><code>"content"</code><code>,txt,Field.Store.YES,Field.Index.ANALYZED));</code>
<code> </code><code>writer.addDocument(doc);</code>
<code> </code><code>writer.close();</code>
<code> </code><code>IndexSearchersearcher = </code><code>new</code> <code>IndexSearcher(IndexReader.open(dir));</code>
<code> </code><code>TopDocstds = searcher.search(</code><code>new</code> <code>TermQuery(</code><code>new</code> <code>Term(</code><code>"content"</code><code>,</code><code>"咱"</code><code>)),</code><code>10</code><code>);</code>
<code> </code><code>Documentd = searcher.doc(tds.scoreDocs[</code><code>0</code><code>].doc);</code>
<code> </code><code>System.out.println(</code><code>"原文:"</code><code>+d.get(</code><code>"content"</code><code>));</code>
<code> </code><code>AnalyzerUtils.displayAllTokenInfo(txt,a2);</code>
<code> </code><code>}</code><code>catch</code> <code>(CorruptIndexException e) {</code>
<code> </code><code>}</code><code>catch</code> <code>(LockObtainFailedException e) {</code>
<code> </code><code>}</code><code>catch</code> <code>(IOException e) {</code>
本文转自 梦朝思夕 51CTO博客,原文链接:http://blog.51cto.com/qiangmzsx/1549902