lucene之基本索引操作

 Lucene将输入数据以一种倒排索引的数据结构进行存储,其原因是倒排索引并不是回答“这个文档中包含哪些单词?”,而是经过优化后快速回答“哪些文档包含这些单词X”,导致最终速度不只是提升一点点。

1  protected String[] ids = {"1", "2"};
2  protected String[] unindexed = {"Netherlands", "Italy"};
3  protected String[] unstored = {"Amsterdam has lots of bridges",
4                                  "Venice has lots of canals"};
5  protected String[] text = {"Amsterdam", "Venice"};
6 
7  private Directory directory;

一、向索引中添加文档

 添加方法:

addDocument(Document) 使用默认分析器添加文档,该分析器在创建IndexWriter对象时指定,用于语汇单元化操作

addDocument(Document,Analyzer) 使用指定分析器

protected void add() throws Exception {     
    directory = new RAMDirectory();

    IndexWriter writer = getWriter();           

    for (int i = 0; i < ids.length; i++) {      
      Document doc = new Document();
      doc.add(new Field("id", ids[i],
                        Field.Store.YES,
                        Field.Index.NOT_ANALYZED));
      doc.add(new Field("country", unindexed[i],
                        Field.Store.YES,
                        Field.Index.NO));
      doc.add(new Field("contents", unstored[i],
                        Field.Store.NO,
                        Field.Index.ANALYZED));
      doc.add(new Field("city", text[i],
                        Field.Store.YES,
                        Field.Index.ANALYZED));
      writer.addDocument(doc);
    }
    writer.close();
  }

二、删除索引中的文档

 IndexWriter类提供的删除方法有:

deleteDocuments(Term) 删除包含项的所有文档

deleteDocuments(Term[]) 删除包含项数组中任一元素的所有文档

deleteDocuments(Query) 删除匹配查询语句的所有文档

deleteDocuments(Query[]) 删除匹配查询语句数组任一元素的所有文档

deleteAll() 删除索引中所有文档

1 public void delete() throws IOException {
2     IndexWriter writer = getWriter();
3     writer.deleteDocuments(new Term("id", "1"));  //删除操作不会马上执行,而是放入内存缓冲区,与加入文档的操作类似。(Lucene会周期性刷新文档目录执行操作 )
4     writer.commit();
5     writer.close();
6   }

三、更新索引中的文档

很多搜索程序在首次索引完成后,由于文档可能后续被更改,需要对它进行再次索引。(目前还做不到更新文档中部分域,实际上现在更新索引的实现相当于做一次删除再做一次添加)

IndexWriter类提供的更新方法有:

updateDocument(Term,Document)   ps:注意确认Term标识的唯一性,否则会一下更新很多

updateDocument(Term,Document,Analyzer)

 1 public void testUpdate() throws IOException {
 2 
 3     IndexWriter writer = getWriter();
 4 
 5     Document doc = new Document();                             
 6     doc.add(new Field("id", "1",
 7                       Field.Store.YES,
 8                       Field.Index.NOT_ANALYZED));   
 9     doc.add(new Field("country", "Netherlands",
10                       Field.Store.YES,
11                       Field.Index.NO));              
12     doc.add(new Field("contents",                    
13                       "Den Haag has a lot of museums",
14                       Field.Store.NO,
15                       Field.Index.ANALYZED));      
16     doc.add(new Field("city", "Den Haag",
17                       Field.Store.YES,
18                       Field.Index.ANALYZED));      
19 
20     writer.updateDocument(new Term("id", "1"),      
21                           doc);                     
22     writer.close();
23   }

四、域选项

1 域索引选项(Field.Index.*)

Index.ANALYZED——使用分析器将域值分解成独立的语汇单元流,适用于普通文本域(如标题、正文、摘要等)。

Index.NOT_ANALYZED——对域索引,但不对String值进行分析,适用于不能被分解的域值(URL、日期、人名、电话号码等)。

Index.NO——对应域值不被搜索

Index.ANALYZED_NO_NORMS——Index.ANALYZED的变体,不在索引中存储norms信息。(域未进行加权操作,那么索引时不能带有norm选项)

Index.NOT_ANALYZED_NO_NORMS

当Lucene建立倒排索引后,默认情况下会计算文档中出term的数量和位置,但有时候我们只关注某些域而不关心他对相关评分做的贡献,此时域只是用作过滤(例如权限过滤和日期过滤)我们可以调用Field.setOmitTermFreqAndPosition(true)来跳过对该项出现频率和出现位置的索引。

2、域存储选项(Field.Store.*):用来确定是否需要存储域的真实值,以便后续搜索能恢复这个值。

Store.YES——对需要展示搜索结果的一些域很有用(如URL、标题、数据库主键),避免存储太大的域值。

Store.NO——通常跟Index.ANALYZED共同索引大的文本域值(如正文)。

Lucene下的工具类CompressionTools提供静态方法压缩解压字节数组(本质是在后台调用java.util.zip类),可以在存储域值之前对它压缩,但是会降低索引和搜索速度(时间换空间),建议少用

3、项向量选项(Field.TermVector.*)(如果你希望搜索期间文档所有的唯一项都能完全从文档域中检索)

该选项是介于索引域和存储域的一个中间结构

TermVector.NO

TermVector.WITH_POSITIONS_OFFSETS

 

posted @ 2013-04-23 15:51  Dream-Weaver  阅读(287)  评论(0编辑  收藏  举报