《lucene in action》笔记:构建索引

1.lucene如何对搜索内容进行建模

1.1文档(document)和域(field)

文档是lucene索引和搜索的原子单位。文档为包含一个或多个域的容器,而域则依次包含真正的被搜索的内容。比如一篇文章就是一个文档,标题是一个域,标题内容为域值,正文也是一个域,正文内容为域值。lucene可以针对域进行三种操作:

  • 域值可以被索引
  • 域被索引后,可以选择性的存储项向量。项向量(TermVector)可以被用作相似查找
  • 域值还可以被单独存储

2.理解索引过程

2.1提取文本和创建文档

使用lucene索引数据时,必须先从数据中提取纯文本格式信息,以便lucene识别该文本并建立对应的lucene文档。tika框架可以轻易的从各种格式的文件中提取文本信息

2.2分析文档

一旦建立起lucene文档和域,就可以调用IndexWriter对象的addDocument方法将数据传递给lucene进行索引操作了。在索引操作时,lucene首先分析文本,将文本数据分割成词汇单元,然后对它们执行一些可选操作。文本分析包含了词汇切割、大小写转换、移除停用词等操作。分析过程的步骤很重要,这一步会产生大量的词汇单元,随后这些词汇单元将被写入索引文件中。

2.3向索引添加文档

对文档分析完毕之后,就可以将分析结果写入索引文件了。lucene将输入数据以一种倒排索引的数据结构进行存储。lucene索引都包含一个或者多个段(segment),每个段都是一个独立的索引,它包含整个文档索引的一个子集。

3.基本索引操作

3.1向索引添加文档

添加文档的方法有两个:

  • addDocument(Document): 使用默认分析器添加文档,该文档分析器在创建IndexWriter对象时指定
  • addDocument(Document, Analyzer): 使用指定的分析器添加文档
3.2删除索引中的文档

IndexWriter提供了各种方法来从索引中删除文档

  • deleteDocuments(Term): 负责删除包含项的所有文档
  • deleteDocuments(Term[]):负责删除包含项数组任一元素的所有文档
  • deleteDocuments(Query): 负责删除匹配查询语句的所有文档
  • deleteDocuments(Query[]): 负责删除匹配查询语句数组任一元素的所有文档
  • deleteAll(): 负责删除索引中的所有文档
3.3更新索引中的文档

IndexWriter提供了两个简便的方法来更新索引中的文档

  • updateDocument(Term, Document):首先删除包含Term变量的所有文档,然后使用writer的默认分析器添加新文档
  • updateDocument(Term, Document, Analyzer):功能与上述一致,区别在于可以指定分析器添加文档

4.域选项

4.1域索引选项
  • Index.ANALYZED:使用分析器将域值分解成词汇单元,并建立索引
  • Index.NOT_ANALYZED: 不使用分析器分解阈值,并建立索引
  • Index.ANALYZED_NO_NORMS: 与Index.ANALYZED类似,但不存储norms信息
  • Index.NOT_ANALYZED_NO_NORMS: 与Index.NOT_ANALYZED类似,但不存储norm信息
  • Index.NO:不建立索引
4.2域存储选项
  • Store.YES: 指定存储阈值
  • Store.NO: 指定不存储阈值
4.3域排序选项

如果需要按照某一域值对匹配的文档集合进行排序,那么该阈值应该被正确的索引以及存储。如果域是数值类型,在将它加入文档和进行排序时,要用NumericField类来表示

4.4多值域

文档的一个域可能有多个值,可以用document.add()多个域相同但域值不同的对象

5.对文档和域进行加权操作

5.1文档加权操作

调用加权操作的API只包含一个方法:documents.setBoost(float)

5.2域加权操作

使用field.setBoost(float)对域进行加权

5.3 加权基准

在索引期间,文档中域的所有加权都被合并成一个单一的浮点数。除了域,文档也有自己的加权值。这些权值被合并到一处,并被编码(量化)成一个单一的字节,作为域或文档信息的一部分存储起来。在搜索期间,被搜索域的norms都被加载到内存,并被解码还原为浮点数,然后用于计算相关性评分(relevance score)。
虽然norms是在索引期间首次进行计算的,后续还是可以使用IndexReader的setNorm方法对它进行修改的。

6.索引数字、日期和时间

6.1索引数字

使用NumricField可以对数字进行索引。每个数值都用特里结构(trie structure)进行索引,能实现高效的范围搜索或者过滤功能。

6.2索引日期和时间

同样使用NumricField索引时间。可以将时间转换成时间戳,在用NumricField

7.域截取

一些应用程序需要对尺寸未知的文档进行索引。IndexWriter允许对域进行截取后再索引它们。传入MaxFieldLength对象告知IndexWriter截取的长度。

8.近实时搜索

lucene通过调用IndexWriter中的对象方法实现近实时搜索:IndexReader getReader()。该方法能实时刷新缓冲区中新增或者删除的文档,然后创建新的包含这些文档的只读型IndexReader实例。

9.优化索引

lucene中索引的优化只是对段(segment)进行合并,这样可以提升搜索效率。思考下搜索功能需要访问各个段中的索引,减少了段的数量也就减少了扫描的次数。优化索引只能提高搜索速度而不是索引速度。IndexWriter提供了4个优化方法:

  • optimize()将索引压缩至一个段,操作完成再返回
  • optimize(int maxNumSegments)也称部分优化,将索引压缩为最多maxNumSegment个段
  • optimize(boolean doWait)跟optimize()类似,若doWait参数传入false值,这样的话调用会立即执行,但合并工作是在后台运行的
  • optimize(int maxNumSegments, boolean doWait)也是部分优化
    注意索引优化会消耗大量的cpu和i/o资源。

10.并发、线程安全及锁机制

10.1线程安全和多虚拟机安全
  • 任意数量的只读属性的IndexReader类都可以同时打开一个索引。
  • 对于一个索引来说,一次只能打开一个Writer。lucene采用文件锁来保证只有一个writer打开索引
  • 任意一个线程都可以共享同一个IndexReader类或者IndexWriter类
10.2索引锁机制

锁文件默认为write.lock,存在于索引目录内。

你可能感兴趣的:(《lucene in action》笔记:构建索引)