Lucene 4.9 学习心得 (一)

来源:转载


Lucene 是一个全文本搜索引擎,提供了诸如 建立索引 以及检索 索引等功能。在本文及后续的文章中将介绍一些有关Lucene的原理及使用方式等内容。本系列文章内容多来自Lucene官方文档,有兴趣的读者可以直接阅读相关文档。 另:目前Lucene的最新版本是4.9,故以此版本作为学习的基础。 lucene下载传送门:http://lucene.apache.org/


在介绍lucene之前,需要理解一些概念(此段摘自http://blog.csdn.net/tianlincao/article/details/6867127):

document
用户提供的源是一条条记录,它们可以是文本文件、字符串或者数据库表的一条记录等等。一条记录经过索引之后,就是以一个Document的形式存储在索引文件中的。用户进行搜索,也是以Document列表的形式返回。
field
    一个Document可以包含多个信息域,例如一篇文章可以包含“标题”、“正文”、“最后修改时间”等信息域,这些信息域就是通过Field在Document中存储的。

    Field有两个属性可选:存储和索引。通过存储属性你可以控制是否对这个Field进行存储;通过索引属性你可以控制是否对该Field进行索引。这看起来似乎有些废话,事实上对这两个属性的正确组合很重要,下面举例说明:还是以刚才的文章为例子,我们需要对标题和正文进行全文搜索,所以我们要把索引属性设置为真,同时我们希望能直接从搜索结果中提取文章标题,所以我们把标题域的存储属性设置为真,但是由于正文域太大了,我们为了缩小索引文件大小,将正文域的存储属性设置为假,当需要时再直接读取文件;我们只是希望能从搜索解果中提取最后修改时间,不需要对它进行搜索,所以我们把最后修改时间域的存储属性设置为真,索引属性设置为假。上面的三个域涵盖了两个属性的三种组合,还有一种全为假的没有用到,事实上Field不允许你那么设置,因为既不存储又不索引的域是没有意义的。
term
term是搜索的最小单位,它表示文档的一个词语,term由两部分组成:它表示的词语和这个词语所出现的field。
tocken
    tocken是term的一次出现,它包含trem文本和相应的起止偏移,以及一个类型字符串。一句话中可以出现多次相同的词语,它们都用同一个term表示,但是用不同的tocken,每个tocken标记该词语出现的地方。
segment
    添加索引时并不是每个document都马上添加到同一个索引文件,它们首先被写入到不同的小文件,然后再合并成一个大索引文件,这里每个小文件都是一个segment。


包 org.apache.lucene.analysis 介绍:

Parsing(解析):

Lucene作为建立索引及对索引进行搜索的库,其只接受纯文本输入,而对于我们的应用程序往往要处理多种不同类型的文件,如HTML, XML, PDF, Word等等。因此,在应用Lucene之前,应用程序要负责将非纯文本形式的文件进行预处理,转化为纯文本文件,然后在交与lucene进行处理。


Tokenization:

Lucene将输入的纯文本文件内容进行 断词 处理,得到一些小的用来索引的元素,成为token,而这整个过程称为Tokenization。

在一些情况下,仅仅对文本内容进行分词处理还不够,还需要一些相应的前期处理及后期处理。

前期处理包括(但不仅限于):

  • 去除HTML标记
  • 转换或者去除掉匹配任意正则表达式或指定的一套字符串的文本内容

后期处理包括(但不仅限于):

  • stemming - 对相应的词进行变换,如将bikes变为bike之类的单复数转换等
  • Stop word filtering – 过滤掉一些无意义的词,如英语中的a an the 等很少被用来检索的无意义的词
  • Text normalization - 去除一些方言及其他特殊词汇,优化搜索
  • Synonym extension - 在相同的token位置为一些词添加同义词,优化搜索

一些提示:

Analyzer 和 Tokenizer 常常令人令人迷惑,下面罗列一些他们之间的区别:

  • Analyzer负责为整个文本内容创建token,而Tokenizer仅仅负责将输入的文本内容分割成token。即 由Tokenizer生成的token可能会被更改甚至被Analyzer忽略掉(可以通过在返回结果之前设置一个或多个TokenFilter来实现)
  • Tokenizer是抽象类TokenStream的一个具体子类,而Analyzer则不是。
  • Analyzer 由filed的概念,而Tokenizer则没有

关于TokenStream和field等概念后续文章会有讲解。

Lucene提供了许多用来执行Analyze功能的类,他们均是Analyzer的子类,最常用的则是StandardAnalyzer类。尽管StandardAnalyzer类足以满足许多成熟的应用需求,然而还是有一些很有用的类或者包值得我们在此处提一下:

  1. PerFieldAnalyzerWrapper ---- 大多数Analyzer都是对所有的filed执行相同的操作,而PerFieldAnalyzerWrapper可以将一个Analyzer跟一个Field关联起来,这样就可以为不同的Field设置不同的Analyzer。
  2. 在Lucene根文件夹下analysis库包含了许多不同的Analyzer实现,用来解决与搜索相关的不同问题。许多Analyzer都是被设计用来处理非英语语言的。
  3. 在这个包中,有许多Tokenizer 和 TokenFilter的实现,浏览过后或许你会找到自己所需要的那个。

Analysis是在索引过程中影响性能的主要因素,简而言之,在多数情况下,分析量越大,索引速度越慢。benchmark库可以被用来测试analysis过程的速度。


调用Analyzer:

应用程序一般不需要主动调用Analyzer--Lucene提我们做这些工作:

  • 在索引建立阶段,当调用addDocument(doc)时,实际上为所添加Document的每个需要建立索引的filed都调用了Analyzer
  • 在搜索阶段,QueryParser可能会在解析过程中调用Analyzer。注意:对于某些查询,可能不存在Analyzer调用,如通配符查询等

然而为了测试或其他目的,应用程序也可以直接为一些文档调用Analyzer,就像下面所示的那样:

Version matchVersion = Version.LUCENE_XY; // Substitute desired Lucene version for XY Analyzer analyzer = new StandardAnalyzer(matchVersion); // or any other analyzer TokenStream ts = analyzer.tokenStream("myfield", new StringReader("some text goes here")); OffsetAttribute offsetAtt = ts.addAttribute(OffsetAttribute.class); try { ts.reset(); // Resets this stream to the beginning. (Required) while (ts.incrementToken()) { // Use AttributeSource.reflectAsString(boolean) // for token stream debugging. System.out.println("token: " + ts.reflectAsString(true)); System.out.println("token start offset: " + offsetAtt.startOffset()); System.out.println(" token end offset: " + offsetAtt.endOffset()); } ts.end(); // Perform end-of-stream operations, e.g. set the final offset. } finally { ts.close(); // Release resources associated with this stream. }<span style="font-size:18px;"><span style="font-size:24px;">关于编写自己的Analyzer,具体的请见官方文档,此处不再赘述</span></span>



分享给朋友:
您可能感兴趣的文章:
随机阅读: