Lucene的学习与总结

一、Lucene的基础(2017-05-11 10:40:46)

1、Lucene的下载

API的下载:http://pan.baidu.com/s/1nvLTG0L

视频资料下载:http://pan.baidu.com/s/1gfOifeF

2、Lucene的使用

        IndexWriter writer = null;
        try {
            writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
            Document doc = null;
            for(int i=0;i<ids.length;i++){
                doc = new Document();
                doc.add(new Field("id",ids[i],Field.Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS));
                doc.add(new Field("email",emails[i],Field.Store.YES,Field.Index.NOT_ANALYZED));
                doc.add(new Field("content",contents[i],Field.Store.NO,Field.Index.ANALYZED));
                doc.add(new Field("name",names[i],Field.Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS));
                //存储数字
                doc.add(new NumericField("attach",Field.Store.YES,true).setIntValue(attachs[i]));
                //存储日期
                doc.add(new NumericField("date",Field.Store.YES,true).setLongValue(dates[i].getTime()));
                //加权操作
                String et = emails[i].substring(emails[i].lastIndexOf("@")+1);
                writer.addDocument(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();
            }
        }
        
    
建立索引
/**
     * 搜索
     */
    public void searcher(){
        try {
            //1、创建Directory
            Directory directory = FSDirectory.open(new File("d:/import/studytool/Lucene/index01"));
            //2、创建IndexReader
            IndexReader reader = IndexReader.open(directory);
            //3、根据IndexReader创建IndexSearcher
            IndexSearcher searcher = new IndexSearcher(reader);
            //4、创建搜索的Query
            //创建parser来确定要搜索文件的内容,第二个参数表示搜索的域
            QueryParser parser = new QueryParser(Version.LUCENE_35, "content", new StandardAnalyzer(Version.LUCENE_35));
            //创建query,表示搜索域为content中包含come的文档
            Query query = parser.parse("come");
            //5、根据Seacher搜索并返回TopDocs
            TopDocs tds = searcher.search(query, 10);
            //6、根据TopDocs获取ScoreDoc对象
            ScoreDoc[] sds = tds.scoreDocs;
            for(ScoreDoc sd : sds){
                //7、根据seacher和ScordDoc对象获取具体的Document对象
                Document d = searcher.doc(sd.doc);
                //8、根据Document对象获取需要的值
                System.out.println(d.get("filename")+"["+d.get("path")+"]");
            }
            //9、关闭reader
            reader.close();
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
搜索

3、基本实例

4、系统架构

5、索引过程的核心类

5.1、IndexWriter

5.2、Directory

5.3、Analyzer

5.4、Document

5.5、Field

6、搜索过程的核心类

6.1、IndexSearcher

6.2、Term

6.3、Query

6.4、TermQuery

6.5、TopDocs

6.6、SocreDoc

二、索引的建立

1、基本概念

2、索引过程

3、索引建立步骤

3.1、创建Directory

3.2、创建Writer

3.3、创建文档并且添加索引

文档和域的概念很重要

  文档相当于表中的每一条记录,域相当于表中的每一个字段

 

3.4、查询索引的基本信息

使用IndexReader进行查询

3.5、删除和更新索引

1、删除

可能得到结果:

2、恢复

3、强制删除(不建议使用)

4、优化和合并(不建议使用)

5、更新索引

4、域选项

4.1、索引域选项

使用Field.Index.*来进行操作

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

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

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

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

Index.NO:不进行索引

4.2、存储域选项

Field.Store.*

YES:(可以还原)

  将会存储域值,原始字符串的值会保存在索引,以此可以进行相应的恢复操作,对于主键,标题可以是这种方式存储

NO:(无法完全还原),可以索引

  不会存储域值,通常与Index.ANAYLIZED合起来使用,索引一些如文章正文等不需要恢复的文档

4.3、最佳实践

NOT_ANALYZED_NOT_NORMS YES 标志符(主键、文件名),电话号码,身份证号,姓名,日期
ANAYLZED YES 文档标题和摘要
ANAYLZED NO 文档正文
NO YES 文档类型,数据库主键(不进行索引)
NOT_ANALYZED NO 隐藏关键字

.fnm    保存的是域选项的信息

.fdt/.fdx  保存的是域Store.YES的信息

.frq     保存的是域选项中词出现的次数(搜索"java"这个词,这个文件就会保存每个文章中java出现的次数)

.norm   保存一些评分信息

.prx    偏移量

.tii/.tis   索引里面所有的索引信息

5、其他知识

5.1、对数字和日期进行索引

5.2、常用的Directory

FSDirectory.open会根据当前的运行环境打开一个最合理的基于File的Directory

new RAMDirectory会从内存中打开directory,好处是速度快,缺点是无法持久化

5.3、IndexReader和IndexWriter的生命周期

 

 三、搜索功能

1、搜索的简单实现(TermQuery)

1.1、创建IndexReder

public IndexSearcher getSearcher() {
        try {
            if(reader == null) {
                reader = IndexReader.open(directory);
            } else {
                IndexReader tr = IndexReader.openIfChanged(reader);
                if(tr != null){
                    reader.close();
                    reader = tr;
                }
            }
            return new IndexSearcher(reader);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

 

1.2、创建IndexSearcher

return new IndexSearcher(reader);

 

1.3、创建Term和TermQuery

IndexSearcher searcher = getsercher();
Query query = new TermQuery(new Term(field,name));

 

 

1.4、根据TermQuery获取TopDocs

TopDocs tds = searcher.search(query,num);
System.out.println(“一共查询了:”+tds.totlHits);
tds.totlHits是总记录数,和传出的num没有任何关系

 

1.5、根据TopDocs获取ScoreDoc

for(ScoreDoc sd : tds.scoreDocs) {
    Document doc = searcher.doc(sd.doc);
}

 

1.6、根据ScoreDoc获取相应文档

for(ScoreDoc sd : tds.scoreDocs) {
    Document doc = searcher.doc(sd.doc);
}

 

2、其他搜索(Query) 

2.1、TermRangerQuery(范围查找)

IndexSearcher searcher = getSearcher();
//field:要查询的field  start:开始字符  end:结束字符  TRUE:开区间 Query query = new TermRangeQuery(field,start,end,true,true); TopDocs tds = searcher.search(query,num); System.out.println(“一共查询了:”+tds.totlHits); for(ScoreDoc sd : tds.scoreDocs) { Document doc = searcher.doc(sd.doc); System.out.println(); }

2.2、NumericRange(查询某个数字的范围)

Query query = NumericRangeQuery.newIntRange(field,start,end,true,true);
TopDocs tds = searcher.search(query,num);
System.out.println("一共查询了:"+tds.totalHits);

 

2.3、PreflxQuery(前缀搜索)

//此时value的值就是通过前缀来匹配
Query query = new PrefixQuery(new Term(field,value));

 

2.4、WildcardQuery(通配符搜索*)

//在传入的value中可以使用通配符:?和*,?表示匹配一个字符,*表示匹配任意多个字符
Query query = new WildcardQuery(new Term(field,vlaue));

 

2.5、BooleanQuery

BoolenQuery可以连接多个子查询
Occur.Must表示必须出现
Occur.SHOULD表示可以出现
Occur.MUST_NOT表示不能出现
//可以连接多个文件
BooleanQuery query = new BoolenQuery();
query.add(new TermQuery(new Term("name","zhangsan")),Occur.Must);
query.add(new TermQuery(new Term("content","like")),Occur.Must);

 

2.6、PhraseQuery(短语查询,不能用于中文搜索)

PhraseQuery query = new PhraseQuery();
query.setSlop(1);
query.add(new Term("content","I"));
query.add(new Term("content","football");

 

2.7、FuzzyQuery(模糊查询)

Query query = new FuzzyQuery(new Term(“name”,"Make"),0.4f,0);

 3、Queryparser

3.1、制定项查找

3.2、制定范围查找

3.3、搜索数字和日期范围

3.4、前缀查找

3.5、布尔查询

4、分页搜索


 

四、分页


 

五、高级搜索

1、搜索排序

2、搜索过滤

posted @ 2017-05-12 11:34  R小哥  阅读(287)  评论(0编辑  收藏  举报