Lucene简单应用--Document的增删改查操作

Lucene是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎.它提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在Java开发环境里Lucene是一个成熟的免费开源工具。就其本身而言,Lucene是很受欢迎的免费Java资讯检索程式库。因公司需要,所以开始爬资料学习,希望得到更多大神的指点.然后把这块做好!

当前版本为4.2, 官方网站: http://lucene.apache.org/

 

在全文索引工具中,都是由3部分组成

1.索引部分

2.分词部分

3.搜索部分

 

建立索引的步骤

1.创建Directory

2.创建IndexWriter

3.创建Document对象

4.为Document添加Field

复制代码
/**
 * Description: 建立索引
 *
 */
public void createIndex(){
    
    IndexWriter indexWriter = null;
    try {
    //1.创建Directory
    Directory directory = new RAMDirectory();  //在内存中建立索引
    //2.创建IndexWriter
    IndexWriterConfig indexWiterConfig = new IndexWriterConfig(Version.LUCENE_36, new StandardAnalyzer(Version.LUCENE_36));
    indexWriter = new IndexWriter(directory, indexWiterConfig);
    //3.创建Document对象
    Document document = new Document();
    //4.为Document添加Field
    File filePath = new File("luence/example");
    for(File file: filePath.listFiles()){ //为该文件夹下的所有文件建立索引
        document = new Document();
        //传入文件内容
        document.add(new Field("content",new FileReader(file)));
        //传入文件名
        document.add(new Field("filename", file.getName(),Field.Store.YES,Field.Index.NOT_ANALYZED));
        //传入文件路径
        document.add(new Field("path",file.getAbsolutePath(),Field.Store.YES,Field.Index.NOT_ANALYZED));
        //5.通过IndexWriter添加文档到索引中
            indexWriter.addDocument(document);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }finally{
        if(indexWriter!=null){
            try {
                indexWriter.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}
复制代码

上面实例中在内存中创建索引.也可以在硬盘上创建索引:

Directory directory2 = FSDirectory.open(new File("F:/luence/index"));    //在硬盘上的F:/luence/index下建立索引

 

搜索操作的步骤:

1.创建Directory

2.创建IndexReader

3.根据IndexReader创建IndexSearcher

4.创建搜索的Query

5.根据Searcher搜索并且返回TopDocs

6.根据TopDocs获取ScoreDoc对象

7.根据Seacher和ScoreDoc对象获取具体的Document对象

8.根据Document对象获取需要的值

9.关闭IndexReader

复制代码
public  void searcher(){
        try {
            //1.创建Directory 在硬盘上的F:/luence/index下建立索引
            Directory directory = FSDirectory.open(new File("F:/luence/index"));    
            //2.创建IndexReader
            IndexReader indexReader = IndexReader.open(directory);
            //3.根据IndexReader创建IndexSearcher
            IndexSearcher indexSearcher = new IndexSearcher(indexReader);
            //4.创建搜索的Query 
            //创建parser来确定要搜索文件的内容,第二个参数表示搜索的域, 实例中为"content",表示在内容中查找
            QueryParser queryParser = new QueryParser(Version.LUCENE_36,"content",new StandardAnalyzer(Version.LUCENE_36));
            //创建query,表示搜索域为content中包含Java关键字的文档
            Query query = queryParser.parse("Java");    //搜索包含关键字Java的信息
            //5.根据Searcher搜索并且返回TopDocs            
            //查询,第二个参数表示显示前10条记录
            TopDocs topDoc = indexSearcher.search(query, 10);
            //6.根据TopDocs获取ScoreDoc对象
            ScoreDoc[] scoreDocs = topDoc.scoreDocs;
            for(ScoreDoc scoreDoc : scoreDocs){
                //7.根据Seacher和ScoreDoc对象获取具体的Document对象
                Document document = indexSearcher.doc(scoreDoc.doc);
                //8.根据Document对象获取需要的值
                System.out.println(document.get("filename") + "[" + document.get("path") + "]");
            }
            
            //9.关闭IndexReader
            indexReader.close();
        } catch (Exception e) {
            // TODO: handle exception
        }
}
复制代码

文档Document和域Field的关系

文档Document相当于关系表中的每一条记录,域相当于表中的每一个字段,先创建文档,之后为文档添加域.

域存储选项和域索引选项,均需要在域添加的时候设置

 

存储域选项

Field.Store.YES表示把这个域中的内容完全存储到文件中,方便进行文本的还原

Field.Store.NO表示把这个域中的内容不存储到文件中,但是可以被索引,此时内容无法还原(即无法document.get());

 

索引域选项

Field.Index.ANALYZED:进行分词和索引,适用于标题和内容等

Field.Index.NOT_ANALYZED:进行索引,但是不进行分词,像身份证号,姓名,ID等,适用于精确索索

Field.Index.ANALYZED_NO_NORMS:进行分词但是不存储norms信息,这个norms中包括了创建索引的时间和权值等信息

Field.Index.NOT_ANALYZED_NO_NORMS:即不进行分词也不存储norms信息

Field.Index.NO:不进行索引  

 

最佳实践

Field.Index.NOT_ANALYZED_NO_NORMS, Field.Store.YES标识符(主键,文件名),电话号码,身份证号,姓名,日期

Field.Index.ANALYZED, Field.Store.YES文档标题和摘要

Field.Index.ANALYZED, Field.Store.NO文档正文

Field.Index.NO,Field.Store.YES文档类型,数据库主键(不进行索引)

Field.Index.NOT_ANALYZED,Field.Store.NO 隐藏关键字

 

删除文档操作

复制代码
public void delete(){
        IndexWriter indexWriter = null;
        try {
            IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_36,new StandardAnalyzer(Version.LUCENE_36));
            indexWriter = new IndexWriter(directory, indexWriterConfig);
            //参数是一个选项,可以是一个Query,也可以是一个Term,Term是一个精确查找的值
            //此时删除的文档并不会完全被删除,而是存储在一个回收站中,可以恢复
            //使用Reader可以有效的恢复取到的文档数
            indexWriter.deleteDocuments(new Term("id","1"));
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(indexWriter!=null){
                try {
                    indexWriter.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
复制代码

indexWriter.deleteDocuments()文档并不会完全被删除,而是存储在一个回收站中,我们可以编写查询类来进行查询

复制代码
public void query(){
        try {
            IndexReader indexReader = IndexReader.open(directory);
            System.out.println("存储的文档数:" + indexReader.numDocs());
            System.out.println("总存储量:" + indexReader.maxDoc());
            System.out.println("被删除的文档:" + indexReader.numDeletedDocs());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
复制代码

测试程序

复制代码
         LuenceIndex luence = new LuenceIndex("F:/luence/index");
        luence.index();
        
        System.out.println("===== 首次建立索引后进行查询 =====");
        luence.query();
        
        luence.delete();
        System.out.println("===== 调用删除操作后进行查询 =====");
        luence.query();
复制代码

分析程序运行结果

复制代码
===== 首次建立索引后进行查询 =====
存储的文档数:5
总存储量:5
被删除的文档:0
===== 调用删除操作后进行查询 =====
存储的文档数:4
总存储量:5
被删除的文档:1
复制代码

使用IndexReader可以有效的恢复删除到回收站的文档

复制代码
public void recovery(){
        try {
            IndexReader indexReader = IndexReader.open(directory,false);
            //通过IndexReader进行恢复,恢复时,必须把IndexReader的只读(readOnly)设置为false
            indexReader.undeleteAll();
            indexReader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
复制代码

如果要清空回收站中的内容,需要使用IndexWriter中的forceMergeDeletes()方法

复制代码
public void forceDelete(){
        IndexWriter indexWriter = null;
        try {
            IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_36,new StandardAnalyzer(Version.LUCENE_36));
            indexWriter = new IndexWriter(directory, indexWriterConfig);
            indexWriter.forceMergeDeletes();
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(indexWriter!=null){
                try {
                    indexWriter.close();
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
        }
}
复制代码

这次测试

复制代码
public static void main(String[] args) {
        LuenceIndex luence = new LuenceIndex("F:/luence/index");
        luence.index();
        
        System.out.println("===== 首次建立索引后进行查询 =====");
        luence.query();
        
        luence.delete();
        System.out.println("===== 调用删除操作后进行查询 =====");
        luence.query();
        
        luence.forceDelete();
        System.out.println("===== 清空回收站内容后进行查询 =====");
        luence.query();    
}
复制代码

运行结果

复制代码
===== 首次建立索引后进行查询 =====
存储的文档数:5
总存储量:5
被删除的文档:0
===== 调用删除操作后进行查询 =====
存储的文档数:4
总存储量:5
被删除的文档:1
===== 清空回收站内容后进行查询 =====
存储的文档数:4
总存储量:4
被删除的文档:0
复制代码


Luence更新操作

复制代码
public void update(){
        IndexWriter indexWriter = null;
        try {
            IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_36,new StandardAnalyzer(Version.LUCENE_36));
            indexWriter = new IndexWriter(directory, indexWriterConfig);
            //Luence并没有提供更新,这里的更新操作其实是先删除再添加的操作合集
            Document document = new Document();
            document.add(new Field("id","updateId",Field.Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS));
            document.add(new Field("email","updateEmail",Field.Store.YES,Field.Index.NOT_ANALYZED));
            document.add(new Field("content","updateContent",Field.Store.NO,Field.Index.ANALYZED));
            document.add(new Field("name","updateName",Field.Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS));
            //更新Id为2的数据
            indexWriter.updateDocument(new Term("id","2"), document);
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(indexWriter!=null){
                try {
                    indexWriter.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
}
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值