Lucene3.5 的索引的创建,删除,更新,加权

==注意:在涉及到删除,更改之类的改变索引的操作时,要先重新创建一遍索引,然后再执行相关方法才可以看到效果,否则索引仍然是之前的

1. 索引的创建

(1). 第一步先创建模拟的内容,用于创建索引

private String[] ids = {"1","2","3","4","5"};
	private String[] names = {"zhi","dan","feng","zhidan","zhidanfeng"};
	private String[] contents = {"I am zhi, I like you"
			,"I am dan, I like you and I like read book"
			,"I am feng, I am play football"
			,"I am zhidan, I started watch the lucene video"
			,"I am zhidanfeng, I'am studing android"};
	private String[] emails = {"1@qq.com","2@127.com","3@gmail.com","4@126.com","5@qq.com"};

(2). 第二步创建索引要存放的目录对象实例

private Directory directory = null;
	public IndexUtil(){
		try {
			directory = FSDirectory.open(new File("D:/Users/lenovo/workspace/Lucene/luceneIndex/1"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

(3). 创建索引

@Test
	public void createIndex() {
		IndexWriter indexWriter = null;
		try {
			Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_35);
			IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_35, analyzer);
			indexWriter = new IndexWriter(directory, config);
			Document doc = null;
			for(int i = 0; i < ids.length; i++) {
				doc = new Document();
				doc.add(new Field("id", ids[i], Store.YES, Index.NOT_ANALYZED_NO_NORMS));
				doc.add(new Field("name", names[i], Store.YES, Index.NOT_ANALYZED));
				doc.add(new Field("content", contents[i], Store.YES, Index.ANALYZED));
				doc.add(new Field("email", emails[i], Store.YES, Index.NOT_ANALYZED));
				
				// 该句一定要放在for循环里面,一开始我放到了后面,发现删除,更新之类的操作都没起作用
				indexWriter.addDocument(doc);
			}
		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (LockObtainFailedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(indexWriter != null) {
					indexWriter.close();
				}
			} catch (CorruptIndexException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
(4). 选中该createIndex方法,运行该单元测试,可以在该项目下面的【 luceneIndex/1 】下面看到出现了许多文件
至此,索引创建成功


2. 索引的查询

@Test
	public void searcher() {
		try {
			IndexReader reader = IndexReader.open(directory);
			IndexSearcher searcher = new IndexSearcher(reader);
			// 在“content”中查询关键字为“am”的文档
			TermQuery query = new TermQuery(new Term("content", "am"));
			// 设定查询出来的为10条
			TopDocs topDocs = searcher.search(query, 10);
			// 从查询出来的结果中循环打印出相关信息
			for(ScoreDoc scoreDoc : topDocs.scoreDocs) {
				// scoreDOc.doc:获取文档ID
				// searcher.doc(int ID):根据指定的文档ID来获取指定的文档
				Document doc = searcher.doc(scoreDoc.doc);
				System.out.println("("+doc.get("id")+")content:"+doc.get("content"));
			}
			searcher.close();
			reader.close();
		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

为了后面删除文档后查看方便,这里在添加一个查询文档的方法,主要是显示出已创建的文档数目以及已删除的文档数目

@Test
	public void query() {
		try {
			IndexReader reader = IndexReader.open(directory);
			// numDocs:实际的文档数,maxDocs:最大的文档数,即索引一创建时,是多少就是多少
			// 但是当删除某个文档后numDocs的数目会变化,但是maxDocs的数目却不会变化
			// numDeletedDocs:已删除的文档数目
			System.out.println("numDocs="+reader.numDocs()+", maxDocs="+reader.maxDoc());
			System.out.println("deleteDocNum="+reader.numDeletedDocs());
		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

3. 索引的删除

/**
	 * 删除索引,删除之后是放到类似回收站之类的里面去
	 * 可以撤销删除操作
	 */
	@Test
	public void delete() {
		Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_35);
		IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_35, analyzer);
		IndexWriter indexWriter = null;
		try {
			indexWriter = new IndexWriter(directory, config);
			indexWriter.deleteDocuments(new Term("name", "zhi")); // 删除域名为“name”中的值为“zhi”的文档
		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (LockObtainFailedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(indexWriter != null) {
					indexWriter.close();
				}
			} catch (CorruptIndexException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

4. 删除的索引的恢复(类似我们从Windows的回收站中还原项目一样)

/**
	 * 撤销删除索引操作,类似从回收站还原已删除的索引
	 */
	@Test
	public void undo() {
		IndexReader reader = null;
		try {
			// 由于要撤销操作,所以要恢复原有的索引,这就涉及到了更该操作,
			// 而IndexReader默认为只读模式,所以要修改的话,必须将只读模式设为读写模式
			reader = IndexReader.open(directory, false);
			// 还原已删除的文档
			reader.undeleteAll();
			// 关闭资源
			reader.close();
		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

5. 清空已删除的索引(类似清空回收站)

/**
	 * 清空已删除的索引,即类似清空回收站
	 */
	@Test
	public void forceDelete() {
		Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_35);
		IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_35, analyzer);
		IndexWriter indexWriter = null;
		try {
			indexWriter = new IndexWriter(directory, config);
			// 清空
			indexWriter.forceMergeDeletes();
		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (LockObtainFailedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(indexWriter != null) {
					indexWriter.close();
				}
			} catch (CorruptIndexException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

6. 索引的更新

索引的更新:先根据条件删除该索引,然后再依据你定义的条件重新创建一个索引,所以更新后的索引可以不和你更新之前的那个条件相同

换句话来讲:如果我们要更新数据库中的某个ID的数据的话,肯定要根据这个ID来先查找到该条数据,然后执行更新操作,更新之后的ID与更新之前的相同,

但是索引的更新和数据库的更新不同,为先删除后创建,所以更新后的和更新前的内容(id,content之类的)可以不同

/**
	 * 更新索引
	 * 更改文档,其实就是先删除,然后再重新创建一个索引
	 */
	@Test
	public void update() {
		Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_35);
		IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_35, analyzer);
		IndexWriter indexWriter = null;
		try {
			indexWriter = new IndexWriter(directory, config);
			Document document = new Document();
			
			// 更改文档,其实就是先删除,然后再重新创建一个索引,所以即使你的id不相同
			// 也没有问题,不同于我们在数据库中的更新,id不同就会报错
			document.add(new Field("id", "111", Store.YES, Index.NOT_ANALYZED_NO_NORMS));
			document.add(new Field("name", names[0], Store.YES, Index.NOT_ANALYZED));
			document.add(new Field("content", contents[0], Store.NO, Index.ANALYZED));
			document.add(new Field("email", emails[0], Store.NO, Index.ANALYZED));
			
			indexWriter.updateDocument(new Term("id", "1"), document);
			
		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (LockObtainFailedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(indexWriter != null) {
					indexWriter.close();
				}
			} catch (CorruptIndexException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

7. 索引加权后排序

在没有设置权值之间,我看了一下是根据你所搜索的关键字的出现次数来排序的,所以在添加权值后会先根据权值来排序,权值越大,越排在前面。权值默认为1.0f

(1)现在【1】中的(1)的后面添加如下代码

private Map<String, Float> scores = new HashMap<String, Float>();
(2)现在【1】中的(2)中添加如下代码,可以放在directory的前面

scores.put("qq.com", 2.5f);
	scores.put("gmail.com", 1.5f);
	scores.put("126.com", 2.0f);
(3). 现在【1】中的(2)中添加如下代码,可以放在doc.add...的后面,indexWriter的前面

// 设置加权,值越高,权越大,排序越排在前面
	// 1. 先按权值排序,权值越大,越排在前面,
	// 2. 然后根据查询的关键字来进行排序,关键字出现字数越多,越排在前面
	String et = emails[i].substring(emails[i].lastIndexOf("@")+1);
	if(scores.containsKey(et)) {
		doc.setBoost(scores.get(et));
	} else {
		doc.setBoost(0.5f);
	}
至此加权操作完成,之后先重新创建一次索引,然后执行searcher操作,观察一下排序情况是否和加权之前不同
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值