回顾倒排索引的构建
- 收集待建索引的原文档(Document)
- 将原文档传给词条化工具(Tokenizer)进行文本词条化
- 将第二步得到的词条(Token)传给语言分析工具(Linguistic modules)进行语言学预处理,得到词项(Term)
- 将得到的词项(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
Tokenizer类的主要作用:接收Read对象,读取字符串进行分词并创建Term项。
TokenFilter类使用装饰者模式(lucene in action中作者写的是组合模式,本人窃以为应该是装饰者模式),封装另一个TokenStream类,主要负责处理输入的Token项,然后通过新增、删除或修改Attribute的方式来修改Term流。
如上图,当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]
相关推荐
Lucene学习总结之四:Lucene索引过程分析(1) Lucene学习总结之四:Lucene索引过程分析(2) Lucene学习总结之四:Lucene索引过程分析(3) Lucene学习总结之四:Lucene索引过程分析(4) www.chinaandroid.com
其中总体架构和索引文件格式是Lucene 2.9的,索引过程分析是Lucene 3.0的。 鉴于索引文件格式没有太大变化,因而原文没有更新,原理和架构的文章中引用了前辈的一些图,可能属于早期的Lucene,但不影响对原理和架构...
lucene自带的词频分析功能,该源代码流程为:先从数据库中读取数据,写入TXT文本中,使用lucene进行索引,然后得出词频分析结果。
Lucene的基础知识 ...6、分析器的分析过程 a) 测试分析器的分词效果 b) 第三方中文分析器 7、索引库的维护 a) 添加文档 b) 删除文档 c) 修改文档 Lucene的高级查询、solr入门 solr在项目中的应用及电商搜索实现
1.10 Lucene学习总结之五:Lucene段合并(merge)过程分析 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .160 1.11 Lucene学习总结之六:Lucene打分公式的数学推导 . . . . . . . . . . . . . . . ...
详细分析lucene搜索的实现过程,通过代码解析,会对lucene的搜索实现过程有一个更加深刻的认识
但基本的怎么使用lucene以及对其 原理的分析都很清楚。里面还有一个能跑的工程。 包括源码和一个发布的工程。两者可能有点点不一致。 (less than 1%) 如果在使用过程中有问题可以qq我:125475832 保留版权。勿用于...
给出了具体的实验方法和实验过程,对改进原理和实验数据进行了分析,表明了加入中文分词模块和在索引预处 理模块中采用提取特定数量的特征词来替代文档的方法能够有效提高Lucene检索系统的效率和精度,增强Lucene...
lucene分析,介绍了lucne建立索引以及查询的过程,包括语法分析器,过滤器,切词器,有想了解lucene的同学可以从中获取到自己想要的东西
虽然分析(Analysis)只是Lucene使用中的一个方面,不过却是最需要重视和认真对待的内容。只有在索引过程中经过分析所产生的词才是我们能够搜索到的。
lucene-搜索过程源码解析-1-Weight生成.txt
Lucene索引过程的核心类 IndexWriter :提供对索引的写入操作 Directory:描述了索引存放的位置 Analyzer:对文本进行分析,提取词汇(token),剔除无用的信息 Document:虚拟的文档 Field:每个Document包含一个或...
介绍Lucene的原理,处理流程,以及实例代码,全面分析介绍!
用简单的例子介绍了Lucene的最新应用方法,包括完整的搜索实现过程:从完成索引到搜索用户界面的实现。此外还进一步介绍了实现准实时搜索的方法,展示了Solr的用法以及实现分布式搜索服务集群的方法。最后介绍了在...
1、什么是全文检索,如何实现全文检索 2、Lucene 实现全文检索的流程 3、配置开发环境 4、入门程序 5、分析器的分析过程 6、索引库维护 7、索引库查询
对数据源分析,使用Lucene的分析器(Analyzer),根据分析器所得到的词条,构造一个索引器IndexWriter。索引器IndexWriter的功能主要就是创建索引,是建立索引工作中最核心的。 当构造完一个索引器IndexWriter之后,...
Lucene的知识主要分为索引、搜索、分析器、性能优化几个部分。索引和搜索没啥可说的,看几个例子就会了,来回那一套儿,按部就班做几个实验就熟悉了。分析器是Lucence的精华,又分为分词和过滤两部分,而且中文分词...
分析(Analysis),在Lucene当中指的是将域(Field)文本转换为最基本的索引表示单元——项(Term)的过程。在搜索过程中,这些项用于决定什么样的文档能匹配查询条件。例如,如果这句话“For example, if this ...
本书总结搜索引擎相关理论与实际解决方案,并给出了Java实现,其中利用了流行的开源项目Lucene和Solr,而且还包括...用简单的例子介绍了Lucene的应用方法,包括完整的搜索实现过程:从完成索引到搜索用户界面的实现。
整个课程,按照一个从无到有的过程来展开。所有的数据,来自于互联网,用heritrix去抓取。对于抓取的数据,进行去重,去标签,然后利用lucene 和 solr 进行索引和搜索。 课程的最大特点是内容新颖全面而又通俗易懂...