`

Lucene的分析过程

 
阅读更多

回顾倒排索引的构建

Image(3)

  1. 收集待建索引的原文档(Document)
  2. 将原文档传给词条化工具(Tokenizer)进行文本词条化
  3. 将第二步得到的词条(Token)传给语言分析工具(Linguistic modules)进行语言学预处理,得到词项(Term)
  4. 将得到的词项(Term)传给索引组件(Indexer),建立倒排索引

注:详细文档->倒排索引的理论过程见词项词典及倒排记录表

 

分析操作的使用场景

1.如上,倒排索引的构建阶段

2.针对自由文本的查询阶段

QueryParser parser = new QueryParser(Version.LUCENE_36, field, analyzer);

Query query = parser.parse(queryString);

lucene的Analyzer接收表达式queryString中连续的独立的文本片段,但不会接收整个表达式。

例如:对查询语句"president obama" + harvard + professor,QueryParser会3次调用分析器,首先是处理文本“president obama”,然后是文本“harvard”,最后处理“professor”。

3.搜索结果中高亮显示被搜索内容时(即结果摘要-Snippets的生成),也可能会用到分析操作

 

剖析lucene分析器

 

抽象类Analyzer

Analyzer类是一个抽象类,是所有分析器的基类。

其主要包含两个接口,用于生成TokenStream(所谓TokenStream,后面我们会讲到,是一个由分词后的Token 结果组成的流,能够不断的得到下一个分成的Token。)。

接口:

1.TokenStream tokenStream(String fieldName, Reader reader)

2.TokenStream reusableTokenStream(String fieldName, Reader reader)

 

为了提高性能,使得在同一个线程中无需再生成新的TokenStream 对象,老的可以被重用,所以有reusableTokenStream 一说。

Analyzer 中有CloseableThreadLocal<Object> tokenStreams = newCloseableThreadLocal<Object>(); 成员变量, 保存当前线程原来创建过的TokenStream , 可用函数setPreviousTokenStream 设定,用函数getPreviousTokenStream 得到。在reusableTokenStream 函数中,往往用getPreviousTokenStream 得到老的TokenStream 对象,然后将TokenStream 对象reset 一下,从而可以重新开始得到Token 流。

 

抽象类ReusableAnalyzerBase

ReusableAnalyzerBase extendsAnalyzer,顾名思义主要为tokenStream的重用。

其包含一个接口,用于生成TokenStreamComponents。

接口:

TokenStreamComponents createComponents(String fieldName,Reader reader);

 

reusableTokenStream的实现代码分析:

  public final TokenStream reusableTokenStream(final String fieldName,
      final Reader reader) throws IOException {
    // 得到上一次使用的TokenStream
    TokenStreamComponents streamChain = (TokenStreamComponents)getPreviousTokenStream();
    final Reader r = initReader(reader);
    //如果没有PreviousTokenStream则生成新的, 并且用setPreviousTokenStream放入成员变量,使得下一个可用。
    //如果上一次生成过TokenStream,则reset。reset失败则生成新的。
    if (streamChain == null || !streamChain.reset(r)) {
      streamChain = createComponents(fieldName, r);
      setPreviousTokenStream(streamChain);
    }
    return streamChain.getTokenStream();
  }

内部static类TokenStreamComponents

简单封装输入Tokenizer和输出TokenStream。

 

最简单的一个Analyzer:SimpleAnalyzer

SimpleAnalyzer extendsReusableAnalyzerBase,实现createComponents方法。TokenStream的处理是将字符串最小化,生成按照空格分隔的Token流

  protected TokenStreamComponents createComponents( final String fieldName,
      final Reader reader) {
    return new TokenStreamComponents(new LowerCaseTokenizer(matchVersion , reader));
  }
 

抽象类TokenStream

TokenStream 主要包含以下几个方法:
1. boolean incrementToken()用于得到下一个Token。IndexWriter调用此方法推动Token流到下一个Token。实现类必须实现此方法并更新Attribute信息到下一个Token。
2. public void reset() 重设Token流到开始,使得此TokenStrean 可以重新开始返回各个分词。

 

和原来的TokenStream返回一个Token 对象不同,Lucene 3.0 开始,TokenStream已经不返回Token对象了,那么如何保存下一个Token 的信息呢?
在Lucene 3.0 中,TokenStream 是继承于AttributeSource,其包含Map,保存从class 到对象的映射,从而可以保存不同类型的对象的值。在TokenStream 中,经常用到的对象是CharTermAttributeImpl,用来保存Token 字符串;PositionIncrementAttributeImpl 用来保存位置信息;OffsetAttributeImpl 用来保存偏移量信息。所以当生成TokenStream 的时候, 往往调用CharTermAttribute tokenAtt = addAttribute(CharTermAttribute.class)将CharTermAttributeImpl添加到Map 中,并保存一个成员变量。在incrementToken() 中, 将下一个Token 的信息写入当前的tokenAtt , 然后使用CharTermAttributeImpl.buffer()得到Token 的字符串。

注:Lucene 3.1开始废弃了TermAttribute和TermAttributeImpl,用CharTermAttribute和CharTermAttributeImpl代替。

 

Token attributes

如上述,Token的信息真正存在于各个AttributeImpl中,lucene内建的所有Attribute接口都在org.apache.lucene.analysis.tokenattributes包中。

 

Token attributes API的使用

1. 调用addAttribute(继承于AttributeSource)方法,返回一个对应属性接口的实现类,以获得需要的属性。

2. 递归TokenStream incrementToken()方法,遍历Token流。当incrementToken返回true时,其中Token的属性信息会将内部状态修改为下个词汇单元。

3. lucene内建Attribute接口都是可读写的,TokenStream 在遍历Token流时,会调用Attribute接口的set方法,修改属性信息。

 

lucene内建常用Attribute接口

1. CharTermAttribute      保存Token对应的term文本,Lucene 3.1开始用CharTermAttribute代替TermAttribute

2. FlagsAttribute             自定义标志位

3. OffsetAttribute            startOffset是指Term的起始字符在原始文本中的位置,endOffset则表示Term文本终止字符的下一个位置。偏移量常用于搜索结果中高亮Snippets的生成

4. PayloadAttribute          保存有效负载

5. TypeAttribute              保存Token类型,默认为"word",实际中可根据Term的词性来做自定义操作

6. PositionIncrementAttribute 

保存相对于前一个Term的位置信息,默认值设为1,表示所有的Term都是连续的,在位置上是一个接一个的。如果位置增量大于1,则表示Term之间有空隙,可以用这个空隙来表示被删除的Term项(如停用词)。位置增量为0,则表示该Term项与前一个Term项在相同的位置上,0增量常用来表示词项之间是同义词。位置增量因子会直接影响短语查询和跨度查询,因为这些查询需要知道各个Term项之间的距离。

注:并不是所有的Attribute信息都会保存在索引中,很多Attribute信息只在分析过程使用,Term进索引后部分Attribute信息即丢弃。(如TypeAttribute、FlagsAttribute在索引阶段都会被丢弃)

 

Lucene Token流 揭秘

lucene Token流的生成,主要依赖TokenStream 的两个子类Tokenizer和TokenFilter

tokenstream

Tokenizer类的主要作用:接收Read对象,读取字符串进行分词并创建Term项。

TokenFilter类使用装饰者模式(lucene in action中作者写的是组合模式,本人窃以为应该是装饰者模式),封装另一个TokenStream类,主要负责处理输入的Token项,然后通过新增、删除或修改Attribute的方式来修改Term流。

Image(25)

 

如上图,当Analyzer从它的tokenStream方法或者reusableTokenStream方法返回tokenStream对象后,它就开始用一个Tokenizer对象创建初始Term序列,然后再链接任意数量的TokenFilter来修改这些Token流。这被称为分析器链(analyzer chain)。

 

一个简单的Analyzer:StopAnalyzer

  protected TokenStreamComponents createComponents(String fieldName,
      Reader reader) {
    //LowerCaseTokenizer接收Reader,根据Character.isLetter(char)来进行分词,并转换为字符小写
    final Tokenizer source = new LowerCaseTokenizer(matchVersion , reader);
    //只有一个分析器链StopFilter,来去除停用词
    return new TokenStreamComponents(source, new StopFilter(matchVersion ,
          source, stopwords));
  }
 

StopAnalyzer测试

String text = "The quick brown fox jumped over the lazy dog";
System. out.println("Analyzing \"" + text + "\"");
Analyzer analyzer = new StopAnalyzer(Version.LUCENE_36);
String name = analyzer.getClass().getSimpleName();
System. out.println("" + name + ":");
System. out.print("" );
AnalyzerUtils. displayTokens(analyzer, text);
System. out.println("\n" );
 

结果输出

Analyzing "The quick brown fox jumped over the lazy dog"

  StopAnalyzer:

    [quick] [brown] [fox] [jumped] [over] [lazy] [dog]

 

 

作者:God bless you
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
分享到:
评论

相关推荐

    lucene3源码分析

    Lucene的索引过程是一个复杂而有序的操作流程,主要步骤如下: - **1. 创建IndexWriter对象**:初始化索引写入器。 - **2. 创建文档Document对象,并加入域(Field)**:定义文档结构和内容。 - **3. 将文档加入...

    Lucene 原理与代码分析完整版.pdf

    本书不仅提供了理论上的全面解析,还辅以丰富的代码实例,帮助读者从源码层面理解Lucene的工作流程。下面,我们将基于给定文件的关键信息,提炼并扩展关于Lucene原理与代码分析的知识点。 ### 全文检索的基本原理 ...

    Lucene 3.0 原理与代码分析PDF

    Lucene学习总结之四:Lucene索引过程分析(1) Lucene学习总结之四:Lucene索引过程分析(2) Lucene学习总结之四:Lucene索引过程分析(3) Lucene学习总结之四:Lucene索引过程分析(4) www.chinaandroid.com

    Lucene 原理与代码分析完整版

    整个Lucene的工作流程表明,它将文档处理、索引构建、搜索算法和打分机制集成为一个功能强大的全文搜索引擎,其内部实现包含了复杂的算法和数据结构。了解和掌握Lucene的原理与代码实现,对于开发高效稳定的搜索引擎...

    lucene相关jar+查询分析器jar

    1. **Lucene的组件和工作流程**:Lucene主要包括索引和查询两个主要阶段。在索引阶段,它将文本数据转换成倒排索引,这是一个能够快速查找包含特定词汇的文档的数据结构。在查询阶段,用户输入的查询会被解析,然后...

    lucene 原理与代码分析

    ### Lucene段合并(merge)过程分析 段合并是Lucene维护索引效率的关键过程,包括选择要合并的段、合并反向信息、更新索引结构等步骤。通过段合并,可以减少磁盘上的段数量,从而提高查询速度。 以上概述了Lucene的...

    Lucene 原理与代码分析.pdf

    搜索首先对用户查询语句进行分析,分析过程包括词法分析、语法分析和语言处理,与创建索引时的处理类似。之后根据分析得到的语法树来搜索索引文件,匹配到的文档通过评分算法进行排序,最终返回给用户。评分算法是...

    lucene原理与代码分析完整版

    #### 四、Lucene索引过程分析 索引过程是Lucene的核心功能之一,主要包括以下几个步骤: 1. **文档解析**:将原始文档转换为Lucene能够处理的格式。 2. **分词**:将文档内容分解成一系列单词或词组。 3. **规范化...

    lucene开发流程

    要理解Lucene的开发流程,我们首先需要了解其基本概念和步骤。以下是对Lucene开发流程的详细说明: 1. **数据获取**: 开发流程的第一步是从各种数据源(如新闻、论坛、博客)中获取信息。这通常涉及到与数据库...

    深入了解Lucene之一 系统结构分析.pptx

    6. **搜索**:查询字符串经过类似分析过程后,与索引进行匹配,返回相关文档。 ### **4. Lucene索引文件结构** Lucene的索引文件主要由以下部分组成: - **倒排索引(Inverted Index)**:记录了每个项在哪些文档...

    基于lucene的词频分析源代码

    本项目是基于Lucene实现的一个词频分析示例,其主要流程包括以下步骤: 1. **数据预处理**: 在此阶段,数据首先从数据库中读取。这通常涉及SQL查询,将所需的数据提取到内存或临时文件中。数据可能包含各种格式,...

    lucene源码分析1111

    Analyzer还包括TokenStream接口,允许自定义词项分析流程。 4. **查询解析** - QueryParser类负责将用户输入的查询字符串转换为Query对象。它支持多种查询语法,如布尔查询、短语查询、范围查询等。自定义...

    Lucene_原理与代码分析完整版

    #### 五、Lucene段合并过程分析 随着新文档的不断添加,Lucene会定期进行段合并操作,以优化索引结构并减少磁盘空间占用。段合并过程包括选择要合并的段、合并索引信息、更新索引结构等多个步骤。这些操作旨在确保...

    Lucene 3.0 原理与代码分析完整版

    Lucene的核心思想是将文本转换为倒排索引,使得搜索过程高效快速。 二、Lucene索引流程 1. 文档分词:Lucene使用Analyzer对输入的文档进行分词,生成Token流。 2. 字符串到Term:将分词结果转化为Term对象,每个...

    lucene分析

    《Lucene分析:深入理解搜索引擎核心技术》 Lucene,作为Apache软件基金会的开源项目,是Java语言编写的一个全文检索库,被广泛应用于各种搜索引擎的开发中。它提供了文本的索引和搜索功能,使得开发者可以方便地在...

    Lucene+3.0+原理与代码分析完整版

    综上所述,**Lucene 3.0 原理与代码分析**覆盖了全文检索的基础理论、Lucene 的总体架构、索引文件格式、索引过程、段合并过程、打分公式、搜索过程、查询语法、查询对象、分词器等多个方面,为开发者提供了深入理解...

    lucene in action英文版 lucene 3.30包

    索引过程包括分析、分词、倒排索引等步骤。分析是将原始文本拆分为有意义的单元(如单词),分词是将文本转化为可索引的单元。倒排索引是Lucene的核心,它将每个词对应到包含该词的文档列表,便于快速查找。 3. **...

    lucene学习

    Lucene的基础知识 ...6、分析器的分析过程 a) 测试分析器的分词效果 b) 第三方中文分析器 7、索引库的维护 a) 添加文档 b) 删除文档 c) 修改文档 Lucene的高级查询、solr入门 solr在项目中的应用及电商搜索实现

Global site tag (gtag.js) - Google Analytics