Lucene

Lucene 是一款高性能的、可拓展的信息检索(IR)工具库。信息检索是指文档搜索、文档内信息搜索或者文档相关的元数据搜索等操作。

爬虫开源软件:

  • Solr:支持从关系数据库和XML文档中提取原始数据,以及能够通过集成Tika来处理复杂文档。
  • Nutch:包含大规模的爬虫工具,能够抓取和分辨Web站点数据
  • Grub:比较流行的开源web爬虫工具
  • Aperture:支持从web站点、文件系统和邮箱中抓取,并解析和索引其中的文件。

常见的搜索理论模型:

  • 纯布尔模型 :文档不管是否匹配查询请求,都不会被评分。在该模型下,匹配文档与评分不相关,也是无序的;一条查询仅获取所有匹配文档集合的一个子集。
  • 向量空间模型:查询语句和文档都是高维空间的向量模型,这里的每一个独立的项都是一个维度。查询语句和文档之间的相关性或相似性由各自向量之间的距离计算得到。
  • 概率模型:在该模型中,采用全概率方法来计算文档和查询语句的匹配概率.

索引过程核心类

  • IndexWriter :负责创建新索引或者打开已有索引,以及向索引中添加、删除或更新被索引文档的信息。
  • Directory:描述了Lucene索引的存放位置。它是一个抽象类,它的子类负责具体指定索引的存储路径。
  • Analyzar:负责从被索引文本文件中提取词汇单元,并提出剩下的无用信息。分析器的分析对象为文档,该文档包含一些分离的能被索引的域。
  • Document:文档对象代表一些域(Field)的集合。Lucene只处理从二进制文档中提取的以Field实例出现的文本。
  • Field:指包含能被索引的文本内容的类。
  • IndexSearcher:用于搜索由IndexWriter类创建的索引。
  • Term:搜索功能的基本单元。与Field对象类似,Term对象包含一对字符串元素:域名和单词(或域文本值)。
  • Query: 查询类。
  • TermQuery:最基本的查询类型,也是简单查询类型之一。用来匹配指定域中包含特定项的文档。
  • TopDocs:一个简单的指针容器,指针一般指向前N个排名的搜索结果,搜索结果即匹配查询条件的文档。TopDocs会记录前N个结果中每个结果的int docID(可以用它来恢复文档)和浮点型分数。

Lucene索引都包含一个或多个段,每个段都是一个独立的索引,它包含整个文档索引的一个子集。每当writer刷新缓冲区增加的文档,以及挂起目录删除操作时,索引文件都会建立一个新段。

每个段都包含多个文件,文件格式为_X.[ext],这里X代表段名称,[ext]为拓展名,用来标识该文件对应索引的某个部分。各个独立的文件共同组成了索引的不同各部分(项量值、存储的域、倒排索引,等等)。如果使用混合文件格式(Lucene默认处理方式,可以通过IndexWriter.setUseCompoundFile方法进行修改),那么上述索引文件会被压缩到一个单一的文件:_X.cfs。

段文件,用段_[N]标识,该文件指向所有激活的段。Lucene会首先打开该文件,然后打开它所指向的其他文件。值[N]被称为“the genertion”,它是一个整数,Lucene每次向索引提交更改时都会将这个数加1.
IndexWriter类会周期性的选择一些段,然后将他们合并到一个新段中,然后删除老的段。被合并段的选取策略由一个独立的MergePolicy类主导。

域索引选项

  • Index.ANALYZED:使用分析器将值域分解成独立的语汇单元流,并使每个语汇单元能被搜索。该选项使用于普通文本域(如正文、标题、摘要等)。
  • Index.NOT_ANALYZED:对域进行索引,但不对String值进行分析。该操作实际上将值域作为单一语汇单元并使之能被搜索。该选项适用于索引那些不能被分解的值域,如URL、文件路径、日期、人名、社保号码和电话号码等。该选项尤其适用于“精确匹配”搜索。
  • Index.ANALYZED_NO_NORMS:不会在索引中存储norms信息。
  • Index.NOT_ANALYZED_NO_NORMS:不存储norms。用于在搜索期间节省索引空间和减少内存耗费。

域存储选项

  • Store.YES:指定存储域值。该情况下,原始的字符串值全部被保存在索引中,并可以由IndexReader类恢复。该选项对于需要展示搜索结果的一些域很有用(如URL、标题或数据库主键)。如果索引的大小在搜索程序考虑之列的话,不要存储太大的域值,因为存储这些域值会消耗掉索引的存储空间。
  • Store.NO:指定不存储域值。

核心Directory子类

Directory子类

描述

  • SimpleFSDirectory

最简单的Directory子类,使用java.io.* API将文件存入文件系统,不能很好的支持多线程

  • NIOFSDirectory

使用java.nio.* API 将文件保存至文件系统。能很好支持除Windows之外的多线程操作,原因是Sun的JRE在windows平台上长期存在的问题。

  • NMapDirectory

使用内存映射 I/O进行文件访问。对于64位JRE来说是一个很好选择,对于32位JRE并且索引尺寸相对较小时也可以使用该类

  • RAMDirectory

将所有的文件都存入RAM中,但是不推荐使用于较多索引的情况。会造成资源的浪费,以及因为它使用1024字节大小的内部缓冲器。

  • FileSwitchDirectory

使用两个文件目录,根据文件拓展名在两个目录之间切换使用


Lucene 并发处理规则

  • 任意数量的制度只读的IndexReader类都可以同时打开一个索引。在单个JVM内,利用资源和发挥效率最好的办法是用多线程共享单个的IndexReader实例。
  • 对于一个索引来说,一次只能打开一个Writer。lucene采用文件锁来提供保障。一旦建立起IndexWriter对象,系统会分配一个锁,该锁只有当IndexWriter对象被关闭时才会释放。
  • IndexReader 对象甚至可以在IndexWriter对象正在修改索引时打开。每个IndexReader对象将向索引展示自己被打开的时间点。该对象只有在IndexWriter对象提交修改或自己被重新打开后才能获知索引的修改情况。在已经有IndexReader对象被打开的情况下,打开新的IndexReader时采用参数cache=true,这样新的IndexReader会持续检查索引的情况。
  • 任何多个线程都可以共享同一个IndexReader类或IndexWriter类。这些类不仅是线程安全的,而且是线程友好的。

核心锁实现

锁类名

描述

  • NativeFSLockFactory

FSDirectory的默认锁,使用java.nio本地操作系统锁,在JVM还存在的情况下不会释放剩余的被锁文件。但该锁可能无法与一些共享文件系统很好地协同,特别是NFS文件系统

  • SimpleFSLockFactory

使用Java的File.createNewFile API,它比NativeFSLockFactory更易于在不同文件系统间移植。

  • SingleInstanceLockFactory

在内存中创建一个完全的锁,该类是RAMDirectory默认的锁实现子类。在程序知道所有IndexWriter将在同一个JVM实例化时使用该类

  • NoLockFactory

完全关闭锁机制。只有在程序确认不需要使用Lucene通畅的锁保护机制时才能使用它。

IndexReader和IndexWriter删除文档的区别
- IndexReader能够根据文档号删除文档。Indexwriter不能进行这样的操作,因为文档号可能因为段合并操作而立即产生变化。
- IndexReader 可以通过Term对象删除文档,与IndexWriter类似。但IndexReader会返回被删除的文档号,而IndexWriter不能。IndexReader可以立即决定删除哪个文档,因此就能够对这些文档数量进行计算;而IndexWriter仅仅是将被删除的Term进行缓存,后续在进行实际的删除操作。
- 如果程序使用相同的reader进行搜索的话,IndexReader的删除操作会即使生效。IndexWriter的删除操作必须等到程序打开一个新Reader时才能被感知。
- IndexWriter可以通过Query对象执行删除操作,但IndexReader则不行。

在默认情况下,IndexWriter只会在RAM用量为16MB时启动刷新操作。刷新操作是用来释放被缓存的更改的。而提交操作是用来让所有的更改(被缓存的更改或者已经刷新的更改)在索引中保持可视。IndexReader锁看到的一直都是索引的起始状态,直到writer提交更改为止。

IndexSearcher 提供的主要search方法

  • IndexSearcher.search 方法

使用时刻

TopDocs search(Query query, int n)

直接搜索,int n 参数表示返回的评分最高的文档数量

TopDocs search(Query query, Filter filter, int n)

搜索瘦文档子集约束,约束条件基于过滤策略

TopDocs search(Query query,Filter filter, int n ,Sort sort)

搜索受文档子集约束,约束条件基于过滤策略,结果排序通过自定义的sort完成

void search(Query query,Collector results)

当使用自定义文档访问策略时使用,或者不想以默认的前N个搜索结果排序策略收集结果时使用

void search(Query query, Filter filter, Collector results)

结果文档只有在传入过滤策略时才能被接收

搜索类

  • TermQuery:对索引中特定项进行搜索,查询值区分大小写。
  • TermRangeQuery:索引中各个Term对象会按照字典排序顺序进行排列,并允许在Lucene的TermRangeQuery对象提供的范围内进行文本项的直接搜索。
  • NumericRangeQuery:在指定的数字范围内搜索。和TermQuery类一样,newIntRange方法中的两个Boolean参数表示搜索范围是(用true表示)否(用false表示)包含起点和终点。
  • PrefixQuery:搜索包含以指定字符串开头的项的文档。
  • BooleanQuery:可以将各种查询类型组合成复杂的查询方式。BooleanClause.Occur.MUST ,只有匹配该查询语句的文档才在考虑之列。BooleanClause.Occur.SHOULD,该项只是可选项。BooleanClause.Occur.MUST_NOT,意味着搜索结果不会包含任何匹配该查询子举的文档。默认允许包含1024个查询子句,超过最大值时,程序会抛出TooManyClauses异常。
  • PhraseQuery:根据位置信息定位某个距离范围内的项所对应的文档。在匹配的情况下,两个项的位置之间所允许的最大间隔距离称为slop,这里的距离是指项若要按顺序组成给定短语锁需要移动位置的次数。
  • WildcardQuery:使用不完整的、缺少某些字母的项进行查询。*代表0个或者多个字母,?代表0个或者1个字母。
  • FuzzyQuery:用于匹配与指定项相似的项。
  • MatchAllDocsQuery:匹配索引中的所有文档。

常用分析器

  • WhitespaceAnalyzer:通过空格来分割文本信息,而并不对生成的语汇单元进行其他的规范化处理。
  • SimpleAnalyzer:首先通过非字母字符来分割文本信息,然后将语汇单元统一为小写形式。会去掉数字类型的字符,但会保留其他字符。
  • StopAnalyzer:会去除英文中的常用单词(如 the、a等)。
  • StandardAnalyzer:包含大量的逻辑操作来识别某些种类的语汇单元,比如公司名称、E-mail地址以及主机名称等。还会将语汇单元转换为小写形式,并去除停用词和标点符号。

语汇单元属性

  • TermAttribute:语汇单元对应的文本
  • PositionIncrementAttribute:位置增量(默认值为1)
  • OffsetAttriute:起始字符和终止字符的偏移量
  • TypeAttribute:语汇单元类型(默认为单词)
  • FlagsAttribute:自定义标志位
  • PayloadAttribute:每个语汇单元的byte[]类型有效负载

主要可用分析器

  • WhitespaceAnalyzer:根据空格拆分语汇单元
  • SimpleAnalyzer:根据非字母字符拆分文本,将其转换为小写形式
  • StopAnalyzer:根据非字母字符拆分文本,然后小写化,再移除停用词
  • KeywordAnalyzer:将整个文本作为一个单一语汇单元处理
  • StandardAnalyzer:基于复杂的语法来生成语汇单元,该语法能识别E-mail地址、首字母缩写词词、韩语/汉语/日语等字符、字母数字等,还能完成小写转换和移除停用词。

索引文件格式

  • 数据结构
    索引包含了存储的文档(document)正排、倒排信息,用于文本搜索。索引又分为多个段(segments),每个新添加的doc都会存到一个新segment中,不同的segments又会合并成一个segment。segment存储着具体的documents,每个doc有一系列的字段组成,一个field的值是多个词(term),一个term是以一些bytes。其递进关系如下:
    index -> segments -> documents -> fields -> terms
  • 文件格式

    • 全局文件

      • segments_N:记录索引的段数、各段名、各段中文档数、删除数和更新数。可能有多个segments_N文件,最大的N的segments_N是有效文件。
      • segments.gen:记录当前index的代数(generation),即segments_N的最大N。
      • write.lock:阻止多给我IndexWriter同时修改索引,一次只能有一个IndexWriter。
    • 段文件

      • 段描述:
        xxx.si:段的元数据,如此段的文档及相关文件
        xxx.del:删除的doc
      • field信息:
        xxx.fnm:field names,field名称、索引方式。存储域文件的信息
        xxx.fdx:field index,索引xxx.fdt。存储域数据的指针
        xxx.fdt:field data,存储stored fields
      • term信息
        xxx.tip:term index,xxx.tim的索引,实现对xxx.tim的随机存取
        xxx.tim:term directory,按字典顺序排列的terms,其值指向.doc/.pos
        xxx.doc:倒排列表,term所在的docs、在doc中的频率
        xxx.pos:倒排列表,term在doc中的位置
        xxx.pay:payloads and offsets,term在doc中的offset
      • term vector
        term vector 用于打分,存储StoreTermVectors的field
        xxx.tvx:term vector index,每个doc 在xxx.tvd、xxx.tvf中的位置
        xxx.tvd:term vector data file,每个doc的term vector field信息在xxx.tvf中的位置
        xxx.tvf:term vector fields,field的term列表及各term的频率、位置或者偏移
      • 归一化
        xxx.nvm:norms metadata
        xxx.nvd:norms data
      • doc values
        xxx.dvm:DocValues metadata
        xxx.dvd:DocValues data
      • 复合文件
        xxx.cfs,xxx.cfe:复合索引的文件,在系统上虚拟的一个文件,用于频繁的文件句柄
      • 词频文件
        xxx.frq:词频文件,包含文档列表以及每一个term和其词频

你可能感兴趣的:(Lucene)