Lucene5 学习笔记(2) —— 简单介绍 Lucene 搜索功能和索引的修改、删除

先介绍一个使用 IndexWriter 清空索引的功能。因为我们在测试的时候,须要将之前创建的索引都删掉(当然手动删除索引文件也是可以的)。
删除索引和数据库事务一样,先删除到一个回收站中,然后 commit() 以后才会真正删除。

还要强调的一点是 IndexWriter 使用完毕以后是要关闭的。

/**
  * 删除所有索引文件
  */
 public void deleteAll() throws IOException{
     IndexWriter indexWriter = getIndexWriter();
     indexWriter.deleteAll();
     indexWriter.commit();
     indexWriter.close();
     System.out.println("索引目录下的所有索引文件清空完毕!");
 }

使用 Lucene 进行搜索的步骤是:
1、通过 Directory 对象创建 IndexReader 对象
2、通过 IndexReader 对象创建 IndexSearcher 对象
3、创建 Query 对象,传入查询条件,或者通过 QueryParser 对象生成 Query 对象;
4、通过向 IndexSearch 对象中传入 Query 对象,使用 search 方法查询结果 TopDocs 。其实到这里查询结果就出来了,但是我们还要对查询的结果进行进一步的处理;

TopDocs 的含义是 Top Documents,意思就是排名在前面的 Document,Document 在上一节中我们说到,它的含义就相当于一条数据,我们就可以通过 Document 得到数据的相关信息。

5、 从 TopDocs 中得到评分信息, 即 scoreDocs,遍历 scoreDocs 属性,通过 IndexSearch 的 doc() 方法(传入每一个 ScoreDoc 的 doc 属性,类似 id 这个概念),就可以恢复创建索引的时候创建的 Document;

这里说起来晦涩难懂,大家看一看代码就很清楚了。我第一遍写的时候感觉很复杂,写多了,其实都还好。

上面说的这些个步骤,相当于是一个模式,以后我们写搜索的时候,无非就是在这样的一个流程上做一些改动。

 /**
 * 搜索方法 1:针对某个“不分词的”特定项的搜索方法
 */
public void search01() {
    try {
        IndexReader reader = DirectoryReader.open(directory);
        IndexSearcher searcher = new IndexSearcher(reader);
        TermQuery query = new TermQuery(new Term("email","liweipower2015@gmail.com"));
        TopDocs tds = searcher.search(query, 10);
        Document doc = null;
        for(ScoreDoc sd:tds.scoreDocs) {
            doc = searcher.doc(sd.doc);
            // doc.getValues("email")[1]
            System.out.println("doc => "+sd.doc+ " 得分 score => "+sd.score + " name => " + doc.get("name") + " email => " + doc.get("email") + " id => "+doc.get("id"));
        }
        reader.close();
    } catch (CorruptIndexException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

上面的这个例子中的 TermQuery 指的是针对不分词的字段的特定的项进行搜索,也就是我们要找出 email 字段的值为 “liweipower2015@gmail.com” 的数据的前 10 条。

我们还可以对分词的特定项进行搜索。例如,我们的 Query 对象可以这样创建:

TermQuery query = new TermQuery(new Term("content","like"));

content 这个字段是我们经过分词以后的,只要是分词以后的结果中还有 “like” 这个单词的数据都会被我们搜索出来。

IndexReader 有三个重要的方法,这里我们要清楚,我们可以通过下面的这三个方法查看哪些索引信息是被我们删除了,即哪些是删除在回收站里,哪些是真正删除了。IndexReader 使用完毕以后也是要关闭的。

IndexReader reader = DirectoryReader.open(directory);
// 通过 IndexReader 可以获取到文档的数量
System.out.println("numDocs => "+reader.numDocs());
System.out.println("maxDocs => "+reader.maxDoc());
System.out.println("deleteDocs => "+reader.numDeletedDocs());
reader.close();

更新单个索引信息(先删除再添加)

/**
 * 索引的更新:
 * 其实,从来就没有索引的更新操作,实际上是先将索引删除,而后增加
 * 我们可以通过索引的查询方法进行验证,即 IndexReader 的 numDocs()、maxDoc()、numDeletedDocs() 方法
 */
public void update() {
    IndexWriter writer = null;
    try {
        writer = getIndexWriter();
/*
* Lucene并没有提供更新,这里的更新操作其实是如下两个操作的合集
* 先删除之后再添加
*/
        Document doc = new Document();
        doc.add(new StringField("id","7",Field.Store.YES));
        doc.add(new StringField("email","liweipower2015@gmail.com",Field.Store.YES));
        doc.add(new TextField("content","good good study",Field.Store.NO));
        doc.add(new StringField("name","liweiwei",Field.Store.YES));
        writer.updateDocument(new Term("id","1"), doc);
    } catch (CorruptIndexException e) {
        e.printStackTrace();
    } catch (LockObtainFailedException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if(writer!=null) writer.close();
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

单条索引信息的删除,要记得使用 commit() 方法提交删除。

/**
 * 这个方法演示了删除到一个“回收站”的方法
 */
public void delete() {
    IndexWriter writer = null;

    try {
        writer = getIndexWriter();
        // 参数是一个选项,可以是一个Query,也可以是一个term,term是一个精确查找的值
        // 此时删除的文档并不会被完全删除,而是存储在一个回收站中的,可以恢复
        writer.deleteDocuments(new Term("id","6"));
        writer.commit();
    } catch (CorruptIndexException e) {
        e.printStackTrace();
    } catch (LockObtainFailedException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if(writer!=null) writer.close();
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

但是这样的删除,还仅仅只是删除到回收站中,还有可能被搜索到。我们可以使用 IndexWriter 对象的 forceMergeDeletes() 方法清空“回收站”中的索引。看下面的例子。

/**
 * 只调用这个方法,就可以把“删除缓存”(回收站)中删除缓存清空
 * 即 deleteDocs() 方法查询返回 0
 */
public void forceDelete() {
    IndexWriter writer = null;
    try {
        writer = getIndexWriter();
        writer.forceMergeDeletes();
    } catch (CorruptIndexException e) {
        e.printStackTrace();
    } catch (LockObtainFailedException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if(writer!=null) writer.close();
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值