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