`

Lucene源码分析-- Analyzer

    博客分类:
  • JAVA
阅读更多
本文主要分析一下 Lucene输入部分——Analyzer(分析器)。为什么要有Analyzer部分呢?打个比方,人体在消化食物的时候,是不是都要把食物分解掉?食物在肠道里面,被分解成葡萄糖、氨基酸、脂肪等等。变成小块以后,才容易被吸收并加以利用。Lucene也有类似的过程:把文本分解成更小的单元,有词、标点符号、分割符号,甚至还有网站名等等。Analyzer就好比是人体的肠道,它的职责就是把输入的文本切成小的单元。

先看一段代码吧:
#0001  public static void TestAnalyzer()
#0002  {
#0003      Analyzer []analyzers = new Analyzer[4];
#0004      analyzers[0] = new WhitespaceAnalyzer();
#0005      analyzers[1] = new SimpleAnalyzer();
#0006      analyzers[2] = new StopAnalyzer();
#0007      analyzers[3] = new StandardAnalyzer();
#0008      String text = "This is a test document. For more info, please visit Victor's Blog: http://lqgao.spaces.msn.com. ";
#0009      for(int i=0; i<analyzers.Length; i++)
#0010      {
#0011          DumpAnalyzer(analyzers[i], new StringReader(text));
#0012      }
#0013  }
#0014
#0015  public static void DumpAnalyzer(Analyzer analyzer, TextReader reader)
#0016  {
#0017      TokenStream stream = analyzer.TokenStream(reader);
#0018      Token token;
#0019      System.Console.WriteLine(analyzer + " :");
#0020      while ((token = stream.Next()) != null)
#0021      {
#0022          System.Console.Write("[" + token.TermText() + "]");
#0023      }
#0024      System.Console.WriteLine();
#0025      System.Console.WriteLine();
#0026  }
运行结果如下:
Lucene.Net.Analysis.WhitespaceAnalyzer :
[This][is][a][test][document.][For][more][info,][please][visit][Victor's][Blog:]
[http://lqgao.spaces.msn.com.]

Lucene.Net.Analysis.SimpleAnalyzer :
[this][is][a][test][document][for][more][info][please][visit][victor][s][blog][h
ttp][lqgao][spaces][msn][com]

Lucene.Net.Analysis.StopAnalyzer :
[test][document][more][info][please][visit][victor][blog][http][lqgao][spaces][m
sn][com]

Lucene.Net.Analysis.Standard.StandardAnalyzer :
[test][document][more][info][please][visit][victor][blog][http][lqgaospacesmsnco
m]
好,让咱们来分析一下。Lucene中默认提供4个Analyzer:SimpleAnalyzer, StandardAnalyzer, StopAnalyzer, WhitespaceAnalyzer。至于这4个有什么区别,听我慢慢道来。
WhitespaceAnalyzer似乎什么都不做,就是按照white space (空格符号)把文本分开——这样做最省力,最简单。
SimpleAnalyzer 则比WhitespaceAnalyzer进步一些,至少不管大写还是小写的字母,统统变成小写形式。这样做的好处也很明显,不管输入是This tHis还是 THIS thIS,最后都统一为this,便于匹配。除了统一大小写外,SimpleAnalyzer还把标点符号处理了,或者说SimpleAnalyzer是按照标点符号分割单词的。比如`documents.’在SimpleAnalyzer的结果中变为`document’。
StopAnalyzer 看起来和SimpleAnalyzer非常相似,只不过,结果中有一些词被去掉了,比如‘this’, ‘is’, ‘a’, ‘for’等——这些大量出现但没有实际意义的词通常被称为stop word(停用词),并被去掉,不加入索引中。因为这样的词数量很大,但并不能很好的区分文档的内容。去掉stop word能减少索引的规模。
StandardAnalyzer做得要复杂一些了。像”Victor’s”这样的词,被处理为’victor’,并没有”’s”,而且网址也被处理了。稍后我们分析StandardAnalyzer的功能。这几个Analyzer的继承关系如图 1所示。

图 1几种analyzer的类层次图
现在回头再看看Analyzer们是怎么工作的(#0015~#0026)。其实Analyzer是一个工厂模式(Factory Pattern),见#0017。使用时需要其生成一个TokenStream的对象。TokenStream,顾名思义,表示token流,即一个 token序列。每个token都是Token类型的。#0020~#0023展现TokenStream的调用方式。
接下来让我们一步一步地展开Analyzers的细节。既然Token是TokenStream组成的元素,让我们先来看看它的“庐山真面目”。
#0001  public sealed class Token
#0002  {
#0003      internal System.String termText; // the text of the term
#0004      internal int startOffset; // start in source text
#0005      internal int endOffset; // end in source text
#0006      internal System.String type_Renamed_Field = "word"; // lexical type
#0007
#0008      private int positionIncrement = 1;
#0009
#0010      public Token(System.String text, int start, int end)
#0011      public Token(System.String text, int start, int end, System.String typ)
#0012
#0013      public void  SetPositionIncrement(int positionIncrement)
#0014      public int GetPositionIncrement()
#0015      public System.String TermText()
#0016      public int StartOffset()
#0017      public int EndOffset()
#0018      public System.String Type()
#0019  }
可以看出,Token存储了term的字符串(#0003),并记录下起始和终止位置(#0004~#0005),此外还有一个类型信息(#0006)。DumpAnalyzer中调用了TermText()获取字符串信息。
然后看看TokenStream:
#0001  public abstract class TokenStream
#0002  {
#0003      /// <summary>Returns the next token in the stream, or null at EOS. </summary>
#0004      public abstract Token Next();
#0005
#0006      /// <summary>Releases resources associated with this stream. </summary>
#0007      public virtual void  Close()
#0008      {}
#0009  }
TokenStream是一个抽象类,接口只有两个:Next()和Close()。Next()返回当前的token,并指向下一个token;没有token则返回null。
Analyzer也是一个抽象类。默认的TokenStream() (#0005)就是构造并返回一个TokenStream的对象。
#0001  public abstract class Analyzer
#0002  {
#0003      public virtual TokenStream TokenStream(System.IO.TextReader reader)
#0004      {
#0005          return TokenStream(null, reader);
#0006      }
#0007  }
再看它的一个子类WhitespaceTokenizer:
#0001  public class WhitespaceTokenizer:CharTokenizer
#0002  {
#0003      public WhitespaceTokenizer(System.IO.TextReader in_Renamed):base(in_Renamed)
#0004      {}
#0005      protected internal override bool IsTokenChar(char c)
#0006      {
#0007          return !System.Char.IsWhiteSpace(c);
#0008      }
#0009  }
#0010
#0021  public abstract class CharTokenizer : Tokenizer
#0022  {
#0023      public CharTokenizer(System.IO.TextReader input) : base(input)
#0024      {}
#0025
#0026      private int offset = 0, bufferIndex = 0, dataLen = 0;
#0027      private const int MAX_WORD_LEN = 255;
#0028      private const int IO_BUFFER_SIZE = 1024;
#0029      private char[] buffer = new char[MAX_WORD_LEN];
#0030      private char[] ioBuffer = new char[IO_BUFFER_SIZE];
#0031
#0032      protected internal abstract bool IsTokenChar(char c);
#0033      protected internal virtual char Normalize(char c)
#0034      {
#0035          return c;
#0036      }
#0037      public override Token Next()
#0038      {
#0039          int length = 0;
#0040          int start = offset;
#0041          while (true)
#0042          {
#0043              char c;
#0044
#0045              offset++;
#0046              if (bufferIndex >= dataLen)
#0047              {
#0048                  dataLen = input.Read((System.Char[]) ioBuffer, 0, ioBuffer.Length);
#0049                  bufferIndex = 0;
#0050              }
#0051              ;
#0052              if (dataLen <= 0)
#0053              {
#0054                  if (length > 0)
#0055                      break;
#0056                  else
#0057                      return null;
#0058              }
#0059              else
#0060                  c = ioBuffer[bufferIndex++];
#0061
#0062              if (IsTokenChar(c))
#0063              {
#0064                  // if it's a token char
#0065
#0066                  if (length == 0)
#0067                      // start of token
#0068                      start = offset - 1;
#0069
#0070                  buffer[length++] = Normalize(c); // buffer it, normalized
#0071
#0072                  if (length == MAX_WORD_LEN)
#0073                      // buffer overflow!
#0074                      break;
#0075              }
#0076              else if (length > 0)
#0077                  // at non-Letter w/ chars
#0078                  break; // return 'em
#0079          }
#0080
#0081          return new Token(new System.String(buffer, 0, length), start, start + length);
#0082      }
#0083  }
#0084
#0085
#0086  public abstract class Tokenizer : TokenStream
#0087  {
#0088      protected internal System.IO.TextReader input;
#0089      protected internal Tokenizer()
#0090      {}
#0091      protected internal Tokenizer(System.IO.TextReader input)
#0092      {
#0093          this.input = input;
#0094      }
#0095      public override void  Close()
#0096      {
#0097          input.Close();
#0098      }
#0099  }
几个类之间的关系:WhitespaceTokenizerCharTokenizerTokenizerTokenStream。而 CharTokenizer.Next()是一个关键(#0037~#0083)。它从缓冲区中找到分割符(#0062),然后用识别出来的字符串 (#0070)生成一个Token对象(#0081)。其余的Tokenizer只要定义不同的分割符号集合(#0032)就可以了。例如 WhitespaceTokenizer只要告诉Next()“只要不是white space就是分割符号”就可以了(#0005~#0008)。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/alex197963/archive/2008/08/01/2752761.aspx
分享到:
评论

相关推荐

    lucene2.9.1所有最新开发包及源码及文档

    开源全文搜索工具包Lucene2.9.1的使用。 1. 搭建Lucene的开发环境:在classpath中添加lucene-core-2.9.1.jar包 2. 全文搜索的两个工作: 建立索引文件,搜索索引. 3. Lucene的索引文件逻辑结构 1) 索引(Index)由...

    IKAnalyzer中文分词器 3.2.0 源码包.rar

    新版本的IKAnalyzer3.0则发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。 IKAnalyzer3.0特性: 采用了特有的“正向迭代最细粒度切分算法“,具有60万字/秒的高速处理能力...

    word源码java-elasticsearch-analysis-ik-7.3.0:基于IK7.3.0版本使用MySQL远程更新ES的热词库

    word源码java Elasticsearch 的 IK 分析 IK Analysis插件将Lucene IK分析器()集成到elasticsearch中,支持自定义字典。 分析器: ik_smart , ik_max_word ,分词器: ik_smart , ik_max_word 版本 IK版 ES版 掌握 ...

    IKAnalyzer开源轻量级中文分词工具包2012u6

    IK Analyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。...从3.0版本开 始,IK发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。在2012版本中,IK实现了

    IK Analyzer 开源中文分词 2012 u6.zip

    从3.0版本开 始,IK发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。在2012版本中,IK实现了简单的分词 歧义排除算法,标志着IK分词器从单纯的词典分词向模拟语义分词衍化。 ...

    JAVA上百实例源码以及开源项目源代码

    Java 源码包 Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来...

    JAVA上百实例源码以及开源项目

    笔者当初为了学习JAVA,收集了很多经典源码,源码难易程度分为初级、中级、高级等,详情看源码列表,需要的可以直接下载! 这些源码反映了那时那景笔者对未来的盲目,对代码的热情、执着,对IT的憧憬、向往!此时此...

    java开源包8

    AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...

    java开源包1

    AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...

    java开源包10

    AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...

    java开源包11

    AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...

    java开源包2

    AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...

    java开源包3

    AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...

    java开源包6

    AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...

    java开源包5

    AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...

    java开源包4

    AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...

    java开源包7

    AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...

    java开源包9

    AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...

    java开源包101

    AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...

Global site tag (gtag.js) - Google Analytics