Api

Lucene

传入Lucene用于构建索引的纯文本,通常会进行令牌化(tokenization)的过程。令牌化是把输入文本拆分成多个小索引元素的过程,这些元素成为令牌(tokens)。输入文本被分解为令牌的方式在很大程度上影响后面如何搜索该文本。例如,可以识别语句的开头和结尾以提供更准确的短语和相似度搜索(Lucene不提供句子识别)。

在某些情况下,仅将输入文本拆分成令牌是不够的,可能需要更深入的分析。Lucene提供标记前和标记后的分析工具。

标记前工作,比如剥离HTML标签,转换、删除任意匹配的模式串。

笔记后的工作,比如:

Packages

用于将文本转换为可可索引、可搜索标记的库,包括Analyzerarrow-up-right 及相关类。analysis包提供了将Strings和Readers转换为Lucene可以索引的令牌的机制。该包包含四个主要类,所有分析过程由他们派生出来。

定义抽象Analyzerarrow-up-right API,用于将Readerarrow-up-right转换为TokenStreamarrow-up-right 。多个TokenFilterarrow-up-right应用于Tokenizerarrow-up-right的输出组成TokenStreamTokenizersTokenFilters绑定,和 Analyzerarrow-up-right一起使用。analyzers-commonarrow-up-right 提供了多种Analyzer实现,包括StopAnalyzerarrow-up-right 和基于语法的 StandardAnalyzerarrow-up-right

TokenStream 罗列了一系列的token,来自DocumentField或者查询文本,TokenStream是一个抽象类,具体的实现有两个,Tokenizerarrow-up-rightTokenFilterarrow-up-rightTokenizerarrow-up-right 的输入来自ReaderTokenFilterarrow-up-right的输入来自另外一个TokenStream。

提供了对倒排索引结构的编码和解码的抽象,以及可以根据应用程序需求选择的不同实现。

提供一个简单的Document类。Document只是一组命名字段,其值可以是字符串或Reader的实例。

提供了两个主要的类,IndexWriter用于创建索引并将文档添加到索引;IndexReader,用于访问索引中的数据。

提供用于查询的数据结构,比如TermQueryarrow-up-right用于别词,PhraseQueryarrow-up-right 用于词组,BooleanQueryarrow-up-right 用于查询的逻辑组合。IndexSearcherarrow-up-right 将查询转换为 TopDocsarrow-up-right,提供多种 QueryParserarrow-up-right 用于从字符串或者xml生成查询结构。

定义了抽象类 Directoryarrow-up-right,用于持久保存数据,保存了文件名的集合,供IndexOutputarrow-up-right写或IndexInputarrow-up-right读。同时提供了多种实现 ,推荐使用 FSDirectoryarrow-up-right,它尝试高效地使用系统磁盘缓冲区。

包含一些方便的数据结构和util类,比如 FixedBitSetarrow-up-rightPriorityQueuearrow-up-right

Steps

Hints, Tips and Traps

Analyzerarrow-up-rightCharFilterarrow-up-rightTokenizerarrow-up-rightTokenFilterarrow-up-right的关系很容易迷惑。

如果想要使用特定的CharFilterTokenizerTokenFilter组合,最简单的事情是使用Analyzerarrow-up-right的匿名类,提供Analyzer.createComponents(String)arrow-up-rightAnalyzer.initReader(String, java.io.Reader)arrow-up-right。Lucene提供很多Analyzer提供有用的分析链,其中最常用的是StandardAnalyzerarrow-up-rightanalyzers-commonarrow-up-right库为多种语言提供了analyzers,同时允许配置自定义Analyzer。

除了StandardAnalyzer,Lucene包含多种组件,包括分析组件,他们在analysis文件夹下。其中一些支持特定语言,另一些集成外部组件。common文件夹有一些值得注意的通用分析器,包括 PerFieldAnalyzerWrapperarrow-up-right,多数Analyzer在所有的Fieldarrow-up-right上执行相同的操作。PerFieldAnalyzerWrapper可用于将不同的分析器与不同的字段关联。

分析器是构造索引缓慢的主要原因之一。

benchmark对测试分析进程效率非常有帮助。

Invoking the Analyzer

应用程序通常不需要调用分析器,交由Lucene来做。

  • 索引构建阶段, addDocument(doc)arrow-up-right时对索引有效的分析器会被调用,应用于添加的文档的每个索引字段。

  • 搜索阶段,QueryParser有可能在解析阶段调用Analyzer,有些搜索可能不会有分析操作。

应用可以这样执行分析器,用于测试或者其他目的。

Indexing Analysis vs. Search Analysis

选择正确的分析器对于搜索质量至关重要,也会影响索引、搜索性能。对于应用程序来说,正确的分析器取决于输入文本以及解决什么样的问题,这里有一些经验指导:

  • 测试

  • 过多的分析器可能会影响索引性能

  • 索引、搜索过程从相同的分析器开始,否则搜索的时候可能不知道目的是什么...

  • 在某些情况下,需要使用其他分析器进行索引和搜索

    • 某些搜索需要过滤更多停用词

构造自己的分析器和分析组件

构造自己的分析器是最直接的,自定义分析器应该是Analyzerarrow-up-right的子类,它可以使用现有的分析组件CharFilter、Tokenizer、TokenFilter、自定义组件。

字段剖面边界

对相同的field多次调用 document.add(field)arrow-up-right ,我们说每次调用创建会为该字段创建一个剖面(section),实际上针对这些切面,会单独调用tokenStream(field,reader)arrow-up-right 。但是默认的Analyzer行为是把这些剖面当做一个大的剖面,这允许词组搜索和相似搜索可以无缝跨越这些剖面(sections)的边界。比如,像这样添加f字段。

然后,词组搜索ends starts会找到那篇文章。如果需要,可以通过在连续的字段剖面之间引入位置间隙来修改此行为,只需覆盖Analyzer.getPositionIncrementGap(fieldName)arrow-up-right即可。

Reference

最后更新于