- 浏览: 85490 次
- 来自: 济南
文章分类
最新评论
-
lib:
速度很快啊!下手很早啊。
在Raspberry Pi上安装Nodejs环境 -
qalong:
如此好文,哪能不顶
Canvas入门实例08:三次方贝塞尔曲线 -
johnnycmj:
膜拜啊....
简单模拟Google的大马跑啊跑的Doodle -
BuN_Ny:
zeng1990 写道BuN_Ny 写道feizhang666 ...
17) 第二章 索引:优化索引(Optimizing) -
zeng1990:
BuN_Ny 写道feizhang666 写道现在已经是luc ...
17) 第二章 索引:优化索引(Optimizing)
先上示例代码,原意看的就看,不愿意看的先略过,回头再对照着看也行:
import java.io.IOException; import junit.framework.TestCase; import org.apache.lucene.analysis.WhitespaceAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.Term; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; import org.apache.lucene.store.Directory; import org.apache.lucene.store.RAMDirectory; /** * 示例代码: * Lucene中document的基本操作 * (新增、删除、更新) */ public class IndexingTest extends TestCase { protected String[] ids = { "1", "2" }; protected String[] unindexed = { "Netherlands", "Italy" }; protected String[] unstored = { "Amsterdam has lots of bridges", "Venice has lots of canals" }; protected String[] text = { "Amsterdam", "Venice" }; private Directory directory; //---------------------------------------------------------------【新增】 protected void setUp() throws Exception { // A setUp()方法会在每一个测试之前运行,它先创建了一个RAMDirectory用来存储索引信息 directory = new RAMDirectory(); // B 参见 D# IndexWriter writer = getWriter(); // C 遍历所有内容,创建Document及Fields并将Document加入索引 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(); } // D 在RAMDirectory上创建IndexWriter private IndexWriter getWriter() throws IOException { return new IndexWriter(directory, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); } protected int getHitCount(String fieldName, String searchString) throws IOException { // E 创建Searcher IndexSearcher searcher = new IndexSearcher(directory); Term t = new Term(fieldName, searchString); // F 创建简单的单一Term的查询 Query query = new TermQuery(t); // G 获取结果集的数量 int hitCount = TestUtil.hitCount(searcher, query); searcher.close(); return hitCount; } public void testIndexWriter() throws IOException { IndexWriter writer = getWriter(); // H 验证writer中document的数量 assertEquals(ids.length, writer.numDocs()); writer.close(); } public void testIndexReader() throws IOException { IndexReader reader = IndexReader.open(directory); // I 验证searcher中document的数量 assertEquals(ids.length, reader.maxDoc()); assertEquals(ids.length, reader.numDocs()); reader.close(); } //---------------------------------------------------------------【删除】 public void testDeleteBeforeIndexMerge() throws IOException { IndexWriter writer = getWriter(); // 1 索引中有2个document assertEquals(2, writer.numDocs()); // 2 删除第一个document writer.deleteDocuments(new Term("id", "1")); writer.commit(); // 3 验证索引中包含了删除操作 assertTrue(writer.hasDeletions()); // 4 一个被索引的document 一个被删除的document assertEquals(2, writer.maxDoc()); // 5 仅有一个被索引的document assertEquals(1, writer.numDocs()); writer.close(); } public void testDeleteAfterIndexMerge() throws IOException { IndexWriter writer = getWriter(); assertEquals(2, writer.numDocs()); writer.deleteDocuments(new Term("id", "1")); // 5 优化压缩索引 writer.optimize(); writer.commit(); assertFalse(writer.hasDeletions()); // 6 合并后仅剩一个被索引的document assertEquals(1, writer.maxDoc()); assertEquals(1, writer.numDocs()); writer.close(); } //---------------------------------------------------------------【更新】 public void testUpdate() throws IOException { assertEquals(1, getHitCount("city", "Amsterdam")); IndexWriter writer = getWriter(); // 1 创建新的document用来更新, 其city域为Haag Document doc = new Document(); doc.add(new Field("id", "1", Field.Store.YES, Field.Index.NOT_ANALYZED)); doc.add(new Field("country", "Netherlands", Field.Store.YES, Field.Index.NO)); doc.add(new Field("contents", "Amsterdam has lots of bridges", Field.Store.NO, Field.Index.ANALYZED)); doc.add(new Field("city", "Haag", Field.Store.YES, Field.Index.ANALYZED)); // 2 用新创建的document替换之前的 writer.updateDocument(new Term("id", "1"), doc); writer.close(); // 3 验证原来的document不存在了 assertEquals(0, getHitCount("city", "Amsterdam")); // 4 验证新的document被加入索引中 assertEquals(1, getHitCount("city", "Haag")); } }
还需要一个辅助类上面的代码才能够正确运行:
import java.io.IOException; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; public class TestUtil { public static int hitCount(IndexSearcher searcher, Query query) throws IOException { return searcher.search(query, 1).totalHits; } }
1. 新增Document
新增方法有两个:
addDocument(Document) - 采用默认的分析器(analyzer)添加文档 addDocument(Document, Analyzer) - 采用指定的分析器添加文档
需要注意的是,搜索阶段所使用的分析器必须与索引阶段使用的一致,才能正确的搜索到相应结果。
为了简化问题,示例代码中,待索引的内容为String型,而在实际应用中,它们可能来自PDF等,需要先解析哦!
在我们的例子中,构造IndexWriter共传入了三个参数:第一个参数Directory表示索引存储的位置(这里是内存);第二个参数是索引过程中所使用的分析器;第三个参数 MaxFieldLength.UNLIMITED 示意IndexWriter要索引文档中所有的词元。如果IndexWriter检测到指定的Directory中并没有index文件存在,它会先创建一个,否则,IndexWriter会仅为其增加新的document.
IndexWriter还有其它许多构造方法,其中一些接受String或File参数以创建FSDirectory, 还有一些允许你指定是想强制性地创建新索引还是覆盖之前的。更高级的构造器,则允许你设计自己的索引删除策略或是提交策略等。
2. 删除Document
删除方法有四个:
deleteDocuments(Term); deleteDocuments(Term[]); deleteDocuments(Query); deleteDocuments(Query[]);
从它们的参数中你也许已经猜出个大概。你可以删掉包含了特定Term的文档,或是符合Query查询条件的。通常,为你的document设计一个名为"id"的Field是个不错的办法,这样就你可以为每个document设置唯一的id,然后通过如下方式删除它:
writer.deleteDocument(new Term("id", documentID));
同新增方法一样,删除操作不会被立即写入磁盘中,你需要手动调用commit()以提交所有变化或者调用close()关闭writer.
示例代码中调用的两个方法 maxDoc() 和 numDocs(), 它们的区别在于:
maxDoc() 会返回索引中的文档(document)总数,包括删除的和未删除的
numDocs() 仅返回索引中未被删除的文档数
3. 更新Document
更新方法有两个:
updateDocument(Term, Document); updateDocument(Term, Document, Analyzer);
很明显它们的区别在于是否指定特定分析器。
需要指出的是,更新操作实质上仅仅是删除和新增的加合。该操作会先依据指定Term删除相应的document,然后依据第二个参数为索引增加新的document. 遗憾的是,即便你仅修改了document中的某个field,你也需要删除整个document,再为其增加新的document,也就是说,此操作的最小粒度是document而非field.
发表评论
-
20) 第二章 索引:缓冲
2012-04-20 22:38 1401Lucene在添加或删除文 ... -
19) 第二章 索引:用IndexReader删除文档
2012-04-19 22:17 1879除了IndexWriter外,IndexReader也可 ... -
18) 第二章 索引:锁策略--Lucene自身提供的锁实现
2011-07-08 17:57 2214首先需要清楚一个大前提:在同一个索引文件上,一次只能 ... -
17) 第二章 索引:优化索引(Optimizing)
2011-06-23 13:59 1861索引文件的多个段可以合并成一个或少量几个。这样将节省 ... -
16) 第二章 索引:设置Field的截断
2011-06-14 16:57 1150针对Field我们还有最后一个特性要讨论:截断(tru ... -
15) 第二章 索引:设计用来排序的域
2011-06-14 09:38 897这一节非常非常简单,场景是这样的:我们对Luce ... -
14) 第二章 索引:用Lucene索引数字
2011-06-13 14:28 2275索引数字的场景主要有两种:一是把它们当作字符串一 ... -
13) 第二章 索引:用Lucene索引日期和时间
2011-06-10 17:46 2830对Lucene而言,每个域都是String类型。 ... -
12) 第二章 索引:规则(Norms)
2011-06-10 10:32 1117在索引阶段,文档(Document)中每个被索引 ... -
11) 第二章 索引:文档优先策略(Boosting)
2011-06-09 14:47 1147请先确认一句话:“并非人人生而平等!”。对于Docum ... -
10) 第二章 索引:Field中含多个值的问题
2011-06-08 17:17 1644假设你的Document中有一个名为" ... -
9) 第二章 索引:Field的设置
2011-06-08 16:25 1310Field也许算是Lucene索引阶段最重要的类 ... -
Hibernate Search常用注解总结
2011-06-08 14:08 65511. @Indexed -> index ... -
7) 第二章 索引:理解Lucene索引过程
2011-06-07 11:32 1239Lucene索引的API非常简单,然而在其 ... -
6) 第二章 索引:Lucene索引的文档模型
2011-06-07 10:57 11331. 文档(Document)和域(Field) ... -
5) 第一章 初识Lucene:理解核心搜索类
2011-05-31 17:22 11021. IndexSearcher Ind ... -
4) 第一章 初识Lucene:理解核心索引类
2011-05-30 17:18 12551. IndexWriter Index ... -
3) 第一章 初识Lucene:一个简单的实例
2011-05-30 16:37 1212还是看代码来的直接: 1. 索引 imp ... -
2) 第一章 初识Lucene:索引和搜索
2011-05-30 15:31 11451. 为什么需要搜索 为什么需要高效的、准确的搜索 ... -
1) 第一章 初识Lucene:简介
2011-05-30 14:05 14571. Lucene是什么 Lucene是一个高性能 ...
相关推荐
数据库应用技术:第08章_索引与视图 本章主要讲述数据库应用技术中索引和视图的相关知识点。索引是与表或视图关联的磁盘上结构,索引中的键存储在一个结构中,使 SQL Server 可以快速有效地查找与键值关联的行。 ...
- 过多的索引会降低写操作的性能,因此应该权衡读写操作的需求。 ### 结论 在SQL Server 2005中,熟练掌握索引的创建、管理和优化是提高数据库性能的重要技能。通过合理设计索引结构,可以显著提升查询速度,同时...
第二章:SQL的基本函数 第三章:SQL的数据类型 第四章、WHERE子句中常用的运算符 第五章:分组函数 第六章:数据限定和排序 第七章:复杂查询(上):多表连接技术 第八章:复杂查询(下):子查询 第二部分:...
如果采用二级索引,第二级索引占用1KB,剩余255KB用于第一级索引,最多可以存放2056320个记录。 4. 变长数据字段的线性索引组织 对于包含变长数据字段的记录,线性索引需要记录关键码、数据起始地址和数据长度。...
实验目的是基于已有的汽车用品网上商城数据库 Shopping,理解视图和索引的概念和作用,练习视图的基本操作,包括视图的建立、视图的查询、视图的更新、视图的删除,体会视图带来的方便;练习索引的创建和删除,对比...
操作系统是计算机系统中最基本的系统软件,它管理和控制计算机硬件资源,提供各种服务和接口,以便于用户使用计算机。操作系统的核心是进程管理、存储管理、文件管理和设备管理四大模块,本文主要讲解操作系统中进程...
空间数据库与SQL第章-索引与数据完整性 本资源主要介绍了空间数据库与SQL中的索引和数据完整性,涵盖了索引的基本概念、类型、创建方法以及数据完整性的重要性。 一、索引的基本概念 索引是根据表中的一列或多列...
第二章:数据库的创建和管理 第三章:回滚/撤销段.控制文件和重做日志 第四章:表空间 第五章:表 第六章:索引 第七章:视图 第八章:集群 第十章:用户,资源文件,角色喝授权 第十一章:其他管理特性 第十二章:...
第二章:oracle安装 第三章:SQL基础知识 第四章:使用SELECT语句 第五章:数据的限定与排序 第六章:多表连接技术 第二部分:ORACLE SQL高级应用 第一章:使用子查询 第二章:用户访问控制 第三章:Oracle的事务和...
在C语言程序设计的学习过程中,第二章通常会涵盖基础语法和基本编程概念。这份"第二章习题参考答案"提供了对这些概念的实践应用解析,旨在帮助学习者巩固理论知识,提升编程技能。以下是根据标题、描述和标签提取的...
第二章:sql基础 ORACLE数据类型 SQL基本语法 简单查询 SQL函数 多数据表查询 事务控制 第三章:plsql基础 声明及变量 表达式 PL/SQL数据类型 流程控制 异常处理 过程 函数 游标 包 触发器 第...
1. **MATLAB界面**:第二章可能会介绍MATLAB的工作空间、命令窗口、编辑器和图形窗口等基本元素,以及如何在这些环境中执行命令和编写脚本。 2. **变量与数据类型**:MATLAB中的变量创建、赋值,以及各种数据类型...
根据给定的信息,我们可以归纳总结出以下相关的IT知识点: ### 1. 外设与CPU的数据交换机制 ...虽然题目没有完整给出具体的操作细节,但PV操作的基本原理可以帮助我们理解如何通过信号量来协调进程之间的同步问题。
尝试插入两条具有相同`uno`值的记录,由于唯一索引的存在,第二次插入将失败。 12. **再次清空集合**: ```javascript db.collectionIndex.remove({}); ``` 清除集合中的所有文档。 13. **创建复合索引**:...
9. **IO流**:虽然可能不是第二章的重点,但简单的输入输出操作对于读写文件或控制台交互是必要的。学习如何使用System.out.println()进行打印,以及Scanner类进行用户输入,将有助于完成习题。 10. **编程实践**:...
通过本章的学习,学生不仅能掌握索引的理论知识,还能通过动手实践提升实际操作能力,同时培养信息搜集和团队协作的技能。在教学过程中,教师应引导学生积极参与,通过实例解析和课堂实训来巩固所学知识,确保他们...
- **二级索引**: 使用一个索引块来存储指向一级索引块的指针。 - **三级索引**: 使用一个索引块来存储指向二级索引块的指针。 假设每个数据块大小为4K,索引块同样为4K,那么: - 一级索引最多可以索引1K个数据块,...
- 在二级索引情况下,文件最大长度可以通过计算各级索引所能指向的块数得出,如题目中所述的116281K字节。 5. **分页存储管理**: - **逻辑地址到物理地址的转换**依赖于页表,逻辑地址由页号和页内地址组成。 -...
索引的类型涵盖广泛,包括主键索引(不允许重复,且唯一标识一行)、普通索引(无唯一性要求)、唯一索引(不允许重复但允许NULL)、单列索引和联合索引、聚簇索引(数据行和索引存储在一起)和非聚簇索引(索引和...