chapter02_构建索引

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

    1. Document是索引和搜索的原子单位

    2. Document是包含一个或多个Field的容器,而Field中包含真正的被搜索内容

    3. Lucene可以针对Field进行3种操作

      (1) 域值可以被索引

      被索引的域值必须是文本格式,二进制格式的域值只能被存储不能被索引

      (2) 域被索引后,可以选择性的存储项向量,后者可以视为该域的一个小型反向索引集合,通过该向量能够检索该域的所有语汇单元

      (3) 域值可以被单独存储

    4. 当搜索程序通过索引搜索文档时,只有被存储的域才会被作为搜索结果呈现,被索引但未被存储的域不会被作为搜索结果呈现

    5. Lucene和database的区别

      (1) 灵活的架构

      加入Index的每个Doc独立;

      Doc中可以包含任意的域,任意的索引、存储和项向量;

      可以随时对Doc进行索引,不必以前设计Doc的数据结构表;如果随后想向文档中添加域,可以完成添加后重新索引该文档或重建索引。

      (2) 反向规格化

      xml通过标记嵌套表示一个递归的文档结构,database靠join操作将多表连接。但是Lucene的Doc是单一的Doc,所以在创建对应的Lucene文档前,必须对上述递归文档结构和连接点进行反向规格化操作

  2. 理解索引过程

    1. 提取文本和创建文档

      (1) 目标:从数据中提取纯文本格式信息

      (2) 文档类型分类:

      1° txt类

      2° pdf, word类

      3° xml, html类

      (3) 可以结合Tika框架提取文本信息

    2. 分析文档

      (1) 目标:将文本数据分割成语汇单元串,然后执行一些可选操作(例如统一大小写LowerCaseFilter、去掉频繁使用却无意义的词StopFilter、去掉词干PorterStemFilter等)

    3. 向索引Index添加文档Doc

      (1) Lucene 将输入数据以倒排索引的数据结构进行存储

      倒排索引用来回答的是“包含单词X的有哪些文档”(“倒排”的意思是正着想是一个文档包含哪些单词,倒着想是这个单词相关联的有哪些文档)

      (2) Lucene 倒排索引的段结构

                   ------> segment 0
                  |
                  |
       segments_N  ------> segment 1
                  |
                  |
                   ------> segment 2
                  |
                  |
                  .....
      

      (3) Lucene索引包含一个或多个段;每个段都是一个独立的索引,包含整个文档索引的一个子集;

      在搜索索引时,每个段都是单独访问的,然后将结果合并

      每个段包含多个文件,文件格式为 _X.<ext>,其中X代表段名称,<ext>代表扩展名,表示项向量、存储的域、倒排索引等;

      如果使用混合文件格式(默认),那么上述所有文件会被压缩成一个文件:_X.cfs;

  3. 基本索引操作

    1. 向索引添加文档

       addDocument(Document)
      
       addDocument(Document, Analyzer)
      
    2. 删除索引中的文档

       deleteDocuments(Term)  
      
       deleteDocuments(Term[])
      
       deleteDocuments(Query)
      
       deleteDocuments(Query[])
      
       deleteAll()
      

      根据Term删除时,类似于数据库中的主键,这是Term的构造函数

       public Term(String fld, String txt)
      

      fld是键名,txt是键值,删除的是键名为键值的所有Doc

      为了确保通过Term删除可以成功,需要确认在每个文档中都已索引过对应的Field类,并且需要确认所有域值都是唯一的

      在创建该域时,该域需要被索引成未被分析的域防止Analyzer将它分解为语汇单元

       doc.add(new Field(
               "id", ids[i],
               Field.Store.YES,
               Field.Index.NOT_ANALYZED));
      
       其中,Field.Store.YES 和Field.Index.NOT_ANALYZED 都是Field的两个静态内部枚举类型Store和Index的实例
      

      无论是添加Doc还是删除Doc,必须调用writer的commit()或close()方法向索引提交更改,否则会放在内存缓冲区。

    3. 更新索引中的文档

       updateDocument(Term, Document);
      
       updateDocument(Term, Document, Analyzer);
      

      Lucene无法做到只更新旧文档的某些Field,只能全部删除旧文档,然后添加新文档;

      上面两个方法的语义是:删除包含Term的所有文档,然后添加Doc

  4. 未完待续……

发布了391 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/captxb/article/details/103259881