您的位置:首页 > 其它

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

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

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();
}
}<
4000
/pre>

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操作,观察一下排序情况是否和加权之前不同
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息