lucene

Lucene简介

一、Lucene 核心API

  • 索引过程中的核心类

  1. Document文档:他是承载数据的实体(他可以集合信息域Field),是一个抽象的概念,一条记录经过索引之后,就是以一个Document的形式存储在索引文件中的。
  2. Field:Field 索引中的每一个Document对象都包含一个或者多个不同的域(Field),域是由域名(name)和域值(value)对组成,每一个域都包含一段相应的数据信息。
  3. IndexWriter:索引过程的核心组件。这个类用于创建一个新的索引并且把文档 加到已有的索引中去,也就是写入操作。
  4. Directroy:是索引的存放位置,是个抽象类。具体的子类提供特定的存储索引的地址。(FSDirectory 将索引存放在指定的磁盘中,RAMDirectory ·将索引存放在内存中。)
  5. Analyzer:分词器,在文本被索引之前,需要经过分词器处理,他负责从将被索引的文档中提取词汇单元,并剔除剩下的无用信息(停止词汇),分词器十分关键,因为不同的分词器,解析相同的文档结果会有很大的不同。Analyzer是一个抽象类,是所有分词器的基类。
  • 搜索过程中的核心类

  1. IndexSearcher :IndexSearcher 调用它的search方法,用于搜索IndexWriter 所创建的索引。
  2. Term :Term 使用于搜索的一个基本单元。
  3. Query : Query Lucene中含有多种查询(Query)子类。它们用于查询条件的限定其中TermQuery 是Lucene提供的最基本的查询类型,也是最简单的,它主要用来匹配在指定的域(Field)中包含了特定项(Term)的文档。
  4. TermQuery :Query下的一个子类TermQuery(单词条查询) ,Query lucene中有很多类似的子类。

  注意:(1)创建索引是对语汇单元索引,通过词语找文档,这种索引的结构叫倒排索引结构

     (2)传统方法是根据文件找到该文件的内容,在文件内容中匹配搜索关键字,这种方法是顺序扫描方法,数据量大、搜索慢。

             (3)倒排索引结构是根据内容(词语)找文档,如下图:

 

  倒排索引结构也叫反向索引结构,包括索引和文档两部分,索引即词汇表,它的规模较小,而文档集合较大。

二、构建索引

  使用indexwriter对象创建索引

  具体步骤:

  第一步:创建一个indexwriter对象。

    1)指定索引库的存放位置Directory对象

    2)指定一个分析器,对文档内容进行分析。

  第二步:创建document对象。

  第三步:创建field对象,将field添加到document对象中。

  第四步:使用indexwriter对象将document对象写入索引库,此过程进行索引创建。并将索引和document对象写入索引库。

  第五步:关闭IndexWriter对象。

FSDirectory dir = FSDirectory.open(Paths.get(file));
//  分词器
Analyzer analyzer = new IKAnalyzer();
//  索引输出流配置对象
IndexWriterConfig conf = new IndexWriterConfig(analyzer);
indexWriter = new IndexWriter(dir, conf);
Document doc = new Document();
doc.add(new StringField("kid","123" , Field.Store.YES));
indexWriter.close()

  注意:(1)每个Document可以有多个Field

     (2)不同的Document可以有不同的Field

     (3)同一个Document可以有相同的Field(域名和域值都相同)

     (4)每个文档都有一个唯一的编号,就是文档id。

 IndexWriter涉及类

IndexWriterConfig:写索引配置,装载着分词器,提供着配置信息

      使用的分词器,如何打开索引(是新建,还是追加)。还可配置缓冲区大小、或缓存多少个文档,再刷新到存储中。还可配置合并、删除等的策略Directory: 索引存储的方式,文件系统或者内存或数据库

Document:索引存储的内容

Field类型

由字段名name、字段值value(fieldsData)、字段类型 type

是否分词:根据业务需要来判断是否进行分词,分词的目的是为了索引,如名称、描述等,分词后可以用关键词进行索引;另外有些属性不需要分词,需要精准查询,如身份证号,编号等
是否索引:需要被用户关键词搜索的都需要建立索引,不需要被索引的可直接存储,不被索引查询
是否存储:需要给用户返回的信息都需要存储,如不存储则无法返回
 

// StringField类型
Field sField = new StringField("sField", StringField, Field.Store.YES);

//LongField类型
Field lField = new LongField("lField", LongField, Field.Store.YES);

//StoredField类型
Field sField2 = new StoredField("sField2", StoredField, Field.Store.YES);

//TextField类型
Field tField = new TextField("tField", TextField, Field.Store.YES);

//自定义类型
FieldType fieldType = new FieldType();// 重构FieldType类
fieldType.setIndexed(true);// set 是否索引
fieldType.setStored(true);// set 是否存储
fieldType.setTokenized(true);// set 是否分类
fieldType.setOmitNorms(false);// set 是否可以设置权重
Field field = new Field("Field", Field, fieldType);

IndexableFieldType

字段类型:描述该如何索引存储该字段

字段可选择性地保存在索引中,这样在搜索结果中,这些保存的字段值就可获得。 一个Document应该包含一个或多个存储字段来唯一标识一个文档。 未存储的字段,从索引中取得的document中是没有这些字段的。

IndexableFieldType:提供了是否分词,是否存储,是否标准化,如何索引等方法。

包括:stored,tokenized,indexOptions,storeTermVectors,omitNorms,docValueType,point

Lucene中的域选项

域选项主要包括以下几种选项:域索引选项、域存储选项、域的项向量选项、域的排序选项等

索引选项 通过倒排索引来控制域值是否能够被搜索

(低版本)Field.Index

index.ANALYZED:进行分词和索引,适用于标题、内容等 
Index.NOT_ANALYZED:进行索引,但是不进行分词,如果身份证号,姓名,ID等,适用于精确搜索 
Index.ANALYZED_NOT_NORMS:进行分词但是不存储norms信息,这个norms中包括了创建索引的时间和权值等信息 
Index.NOT_ANALYZED_NOT_NORMS:即不进行分词也不存储norms信息 
Index.NO:不进行索引 

(高版本)IndexOptions:

NONE: Not indexed 不索引

DOCS:反向索引中只存储了包含该词的 文档id,没有词频、位置

DOCS_AND_FREQS:反向索引中会存储 文档id、词频

DOCS_AND_FREQS_AND_POSITIONS :反向索引中存储文档id、词频、位置

DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS:反向索引中存储 文档id、词频、位置、偏移量

域存储选项:确定是否存储域的真实值,以便在搜索的时候进行恢复

    Stroe.YES 指定存储域值(web页面的URL,数据库的ID,文章标题等可以进行存储)

                Store.NO 不存储域值

三、索引

查询索引也是搜索的过程。搜索就是用户输入关键字,从索引(index)中进行搜索的过程。根据关键字搜索索引,根据索引找到对应的文档,从而找到要搜索的内容(这里指磁盘上的文件)。

对要搜索的信息创建Query查询对象,Lucene会根据Query查询对象生成最终的查询语法,类似关系数据库Sql语法一样Lucene也有自己的查询语法,比如:“name:lucene”表示查询Field的name为“lucene”的文档信息。

3.1.   创建查询

用户输入查询关键字执行搜索之前需要先构建一个查询对象,查询对象中可以指定查询要搜索的Field文档域、查询关键字等,查询对象会生成具体的查询语法,

例如: 语法 “fileName:lucene”表示要搜索Field域的内容为“lucene”的文档

3.2.   执行查询

搜索索引过程:

根据查询语法在倒排索引词典表中分别找出对应搜索词的索引,从而找到索引所链接的文档链表。

比如搜索语法为“fileName:lucene”表示搜索出fileName域中包含Lucene的文档。

搜索过程就是在索引上查找域为fileName,并且关键字为Lucene的term,并根据term找到文档id列表。

可通过两种方法创建查询对象:

         1)使用Lucene提供Query子类

         Query是一个抽象类,lucene提供了很多查询对象,比如TermQuery项精确查询,NumericRangeQuery数字范围查询等。

         如下代码:

      Query query = new TermQuery(new Term("name", "lucene"));

 

         2)使用QueryParse解析查询表达式

         QueryParse会将用户输入的查询表达式解析成Query对象实例。

         如下代码:

           QueryParser queryParser = new QueryParser("name", new IKAnalyzer());

           Query query = queryParser.parse("name:lucene");

方法一、使用query的子类查询

  实现步骤

  第一步:创建一个Directory对象,也就是索引库存放的位置。

  第二步:创建一个indexReader对象,需要指定Directory对象。

  第三步:创建一个indexsearcher对象,需要指定IndexReader对象

  第四步:创建一个Query的子类对象,指定查询的域和查询的关键词。

  第五步:执行查询。

  第六步:返回查询结果。遍历查询结果并输出。

  第七步:关闭IndexReader对象

Query介绍

1、MatchAllDocsQuery

  使用MatchAllDocsQuery查询索引目录中的所有文档

@Test
    public void testMatchAllDocsQuery() throws Exception {
        //创建一个Directory对象,指定索引库存放的路径
        Directory directory = FSDirectory.open(new File("E:\\programme\\test"));
        //创建IndexReader对象,需要指定Directory对象
        IndexReader indexReader = DirectoryReader.open(directory);
        //创建Indexsearcher对象,需要指定IndexReader对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);
        
        //创建查询条件
        //使用MatchAllDocsQuery查询索引目录中的所有文档
        Query query = new MatchAllDocsQuery();
        //执行查询
        //第一个参数是查询对象,第二个参数是查询结果返回的最大值
        TopDocs topDocs = indexSearcher.search(query, 10);
        
        //查询结果的总条数
        System.out.println("查询结果的总条数:"+ topDocs.totalHits);
        //遍历查询结果
        //topDocs.scoreDocs存储了document对象的id
        //ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            //scoreDoc.doc属性就是document对象的id
            //int doc = scoreDoc.doc;
            //根据document的id找到document对象
            Document document = indexSearcher.doc(scoreDoc.doc);
            //文件名称
            System.out.println(document.get("fileName"));
            //文件内容
            System.out.println(document.get("fileContent"));
            //文件大小
            System.out.println(document.get("fileSize"));
            //文件路径
            System.out.println(document.get("filePath"));
            System.out.println("----------------------------------");
        }
        //关闭indexreader对象
        indexReader.close();
    }

2、TermQuery(精准查询)

TermQuery,通过项查询,TermQuery不使用分析器所以建议匹配不分词的Field域查询,比如订单号、分类ID号等。指定要查询的域和要查询的关键词。

//创建一个TermQuery(精准查询)对象,指定查询的域与查询的关键词
//创建查询
Query query = new TermQuery(new Term("fileName", "apache"));

3、NumericRangeQuery

  可以根据数值范围查询。

//创建查询
//参数:
//1.域名
//2.最小值
//3.最大值
//4.是否包含最小值
//5.是否包含最大值
Query query = NumericRangeQuery.newLongRange("fileSize", 41L, 2055L, true, true);

4、BooleanQuery

  可以组合查询条件。

//创建一个布尔查询对象
BooleanQuery query = new BooleanQuery();
//创建第一个查询条件
Query query1 = new TermQuery(new Term("fileName", "apache"));
Query query2 = new TermQuery(new Term("fileName", "lucene"));
//组合查询条件        
query.add(query1, Occur.MUST);
query.add(query2, Occur.MUST);

Occur.MUST:必须满足此条件,相当于and

Occur.SHOULD:应该满足,但是不满足也可以,相当于or

Occur.MUST_NOT:必须不满足。相当于not

5、PrefixQuery

指定字符串开头字母查询(prefixQuery)
 PrefixQuery query=new PrefixQuery(new Term("city","n"));

6、NumericRangeQuery

指定数字范围查询
 NumericRangeQuery<Integer> query=NumericRangeQuery.newIntRange("id", 1, 2, true, true);

7、短语搜索—PhraseQuery

a)默认坡度为0
PhraseQuery query = new PhraseQuery();
query.add(new Term(“bookname”,”钢”));
query.add(new Term(“bookname”,”铁”));
Hits hits=searcher.search(query); //搜索“钢铁”短语,而非“钢”和“铁”

b)设置坡度,默认为0
PhraseQuery query = new PhraseQuery();
query.add(new Term(“bookname”,”钢”));
query.add(new Term(“bookname”,”铁”));
query.setSlop(1);
Hits hits=searcher.search(query);//搜索“钢铁”或“钢*铁”中含一字

8、多短语搜索—MultiPhraseQuery

a)
MultiPhraseQuery query=new MultiPhraseQuery();

//首先向其中加入要查找的短语的前缀
query.add(new Term(“bookname”,”钢”));

//构建3个Term,作为短语的后缀
Term t1=new Term(“bookname”,”铁”);
Term t2=new Term(“bookname”,”和”);
Term t3=new Term(“bookname”,”要”);

//再向query中加入所有的后缀,与前缀一起,它们将组成3个短语
query.add(new Term[]{t1,t2,t3});
Hits hits=searcher.search(query);
for(int i=0;i<hits.length();i++)
    System.out.println(hits.doc(i));

b)
MultiPhraseQuery query=new MultiPhraseQuery();
Term t1=new Term(“bookname”,”钢”);
Term t2 = new Term(“bookname”,”和”);
query.add(new Term[]{t1,t2});
query.add(new Term(“bookname”,”铁”));

c)
MultiPhraseQuery query=new MultiPhraseQuery();
Term t1=new Term(“bookname”,”钢”);
Term t2 = new Term(“bookname”,”和”);
query.add(new Term[]{t1,t2});
query.add(new Term(“bookname”,”铁”));
Term t3=new Term(“bookname”,”是”);
Term t4=new Term(“bookname”,”战”);
query.add(new Term[]{t3,t4});

方法二、使用queryparser查询

通过QueryParser也可以创建Query,QueryParser提供一个Parse方法,此方法可以直接根据查询语法来查询。Query对象执行的查询语法可通过System.out.println(query);查询。

这个操作需要使用到分析器。建议创建索引时使用的分析器和查询索引时使用的分析器要一致。

 1、queryparser

@Test
    public void testQueryParser() throws Exception {
        //创建一个Directory对象,指定索引库存放的路径
        Directory directory = FSDirectory.open(new File("E:\\programme\\test"));
        //创建IndexReader对象,需要指定Directory对象
        IndexReader indexReader = DirectoryReader.open(directory);
        //创建Indexsearcher对象,需要指定IndexReader对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);
        
        //创建queryparser对象
        //第一个参数默认搜索的域
        //第二个参数就是分析器对象
        QueryParser queryParser = new QueryParser("fileName", new IKAnalyzer());
        //使用默认的域,这里用的是语法,下面会详细讲解一下
        Query query = queryParser.parse("apache");
        //不使用默认的域,可以自己指定域
        //Query query = queryParser.parse("fileContent:apache");
        //执行查询


        //第一个参数是查询对象,第二个参数是查询结果返回的最大值
        TopDocs topDocs = indexSearcher.search(query, 10);
        
        //查询结果的总条数
        System.out.println("查询结果的总条数:"+ topDocs.totalHits);
        //遍历查询结果
        //topDocs.scoreDocs存储了document对象的id
        //ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            //scoreDoc.doc属性就是document对象的id
            //int doc = scoreDoc.doc;
            //根据document的id找到document对象
            Document document = indexSearcher.doc(scoreDoc.doc);
            //文件名称
            System.out.println(document.get("fileName"));
            //文件内容
            System.out.println(document.get("fileContent"));
            //文件大小
            System.out.println(document.get("fileSize"));
            //文件路径
            System.out.println(document.get("filePath"));
            System.out.println("----------------------------------");
        }
        //关闭indexreader对象
        indexReader.close();        
    }

 查询语法

  1、基础的查询语法,关键词查询:

    域名+“:”+搜索的关键字

    例如:content:java

  2、范围查询

    域名+“:”+[最小值 TO 最大值]

    例如:size:[1 TO 1000]

    范围查询在lucene中支持数值类型,不支持字符串类型。在solr中支持字符串类型。

  3、组合条件查询

    1)+条件1 +条件2:两个条件之间是并且的关系and

      例如:+filename:apache +content:apache

    2)+条件1 条件2:必须满足第一个条件,应该满足第二个条件

      例如:+filename:apache content:apache

    3)条件1 条件2:两个条件满足其一即可。

      例如:filename:apache content:apache

    4)-条件1 条件2:必须不满足条件1,要满足条件2

      例如:-filename:apache content:apache

Occur.MUST 查询条件必须满足,相当于and

+(加号)

Occur.SHOULD 查询条件可选,相当于or

空(不用符号)

Occur.MUST_NOT 查询条件不能满足,相当于not非

-(减号)

 第二种查询写法:

  条件1 AND 条件2

  条件1 OR 条件2

  条件1 NOT 条件2

2、MultiFieldQueryParser

  可以指定多个默认搜索域

//可以指定默认搜索的域是多个
String[] fields = {"fileName", "fileContent"};
//创建一个MulitFiledQueryParser对象
MultiFieldQueryParser queryParser = new MultiFieldQueryParser(fields, new IKAnalyzer());
Query query = queryParser.parse("apache");

 IndexSearcher搜索方法

方法

说明

indexSearcher.search(query, n)

根据Query搜索,返回评分最高的n条记录

indexSearcher.search(query, filter, n)

根据Query搜索,添加过滤策略,返回评分最高的n条记录

indexSearcher.search(query, n, sort)

根据Query搜索,添加排序策略,返回评分最高的n条记录

indexSearcher.search(booleanQuery, filter, n, sort)

根据Query搜索,添加过滤策略,添加排序策略,返回评分最高的n条记录

 TopDocs

  Lucene搜索结果可通过TopDocs遍历,TopDocs类提供了少量的属性,如下:

方法或属性

说明

totalHits

匹配搜索条件的总记录数

scoreDocs

顶部匹配记录

注意:

    (1)Search方法需要指定匹配记录数量n:indexSearcher.search(query, n)

    (2)TopDocs.totalHits:是匹配索引库中所有记录的数量

    (3)TopDocs.scoreDocs:匹配相关度高的前边记录数组,scoreDocs的长度小于等于search方法指定的参数n

中文分词器 :

  首先,看一看Lucene自带的中文分词器

  (1)StandardAnalyzer:(标准分词器,也是前面例子中使用的分词器)

    单字分词:就是按照中文一个字一个字地进行分词。

    如:“我爱中国”,
    效果:“我”、“爱”、“中”、“国”。

  (2)CJKAnalyzer

    二分法分词:按两个字进行切分。

    如:“我是中国人”,

    效果:“我是”、“是中”、“中国”“国人”。

  但上边两个分词器无法满足需求。

  (3)SmartChineseAnalyzer

    对中文支持较好,但扩展性差,扩展词库,禁用词库和同义词库等不好处理

  (4)IK-analyzer:

IK Analyzer兼容性问题解决办法

IKanalyzer目前最新版本只支持到lucene4.x、solr4.x

    开发真正使用的第三方中文分词器: 最新版在https://code.google.com/p/ik-analyzer/上,支持Lucene 4.10从2006年12月推出1.0版开始, IKAnalyzer已经推出了4个大版本。最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。从3.0版本开 始,IK发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。在2012版本中,IK实现了简单的分词 歧义排除算法,标志着IK分词器从单纯的词典分词向模拟语义分词衍化。 但是也就是2012年12月后没有在更新。 

使用方法:

  第一步:把jar包添加到工程中

  第二步:把配置文件扩展词典停用词词典添加到classpath下(停用词词典与扩展词词典名称可自行定义,只要在配置文件中配置好就可以了)

 

  注意:扩展词典停用词词典文件的格式为UTF-8,注意是无BOM 的UTF-8 编码。

  配置文件详情

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">  
<properties>  
    <comment>IK Analyzer 扩展配置</comment>
    <!--用户可以在这里配置自己的扩展字典 --> 
    <entry key="ext_dict">ext.dic;</entry> 
    
    <!--用户可以在这里配置自己的扩展停止词字典-->
    <entry key="ext_stopwords">stopword.dic;</entry> 
</properties>

停用词词典与扩展词词典样例:

这样,创建分析器时,用一下代码就好了

Analyzer analyzer = new IKAnalyzer();

注意:搜索使用的分析器要和索引使用的分析器一致,不然搜索出来结果可能会错乱。

 删除索引

   (1)删除全部索引

  说明:将索引目录的索引信息全部删除,直接彻底删除,无法恢复。此方法慎用!!

   //删除全部索引
    @Test
    public void testDeleteAllIndex() throws Exception {
        Directory directory = FSDirectory.open(new File("E:\\programme\\test"));
        Analyzer analyzer = new IKAnalyzer();
        IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);
        IndexWriter indexWriter = new IndexWriter(directory, config);
        //删除全部索引
        indexWriter.deleteAll();
        //关闭indexwriter
        indexWriter.close();
    }

(2)指定查询条件删除

    //根据查询条件删除索引
    @Test
    public void deleteIndexByQuery() throws Exception {
        Directory directory = FSDirectory.open(new File("E:\\programme\\test"));
        Analyzer analyzer = new IKAnalyzer();
        IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);
        IndexWriter indexWriter = new IndexWriter(directory, config);
        //创建一个查询条件
        Query query = new TermQuery(new Term("fileContent", "apache"));
        //根据查询条件删除
        indexWriter.deleteDocuments(query);
        //关闭indexwriter
        indexWriter.close();
    }

 索引库的修改

  更新的原理就是先删除在添加

//修改索引库
    @Test
    public void updateIndex() throws Exception {
        Directory directory = FSDirectory.open(new File("E:\\programme\\test"));
        Analyzer analyzer = new IKAnalyzer();
        IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);
        IndexWriter indexWriter = new IndexWriter(directory, config);
        //创建一个Document对象
        Document document = new Document();
        //向document对象中添加域。
        //不同的document可以有不同的域,同一个document可以有相同的域。
        document.add(new TextField("fileXXX", "要更新的文档", Store.YES));
        document.add(new TextField("contentYYY", "简介 Lucene 是一个基于 Java 的全文信息检索工具包。", Store.YES));
        indexWriter.updateDocument(new Term("fileName", "apache"), document);
        //关闭indexWriter
        indexWriter.close();
    }

 高亮显示 

高亮显示的步骤:

1、通过查询对象,获取查询得分对象

2、通过得分对象,获取对应的片段

3、实例化一个html格式化对象

4、通过html格式化实例和查询得分实例,来实例化Lucene提供的高亮显示类对象。

5、将前面获取到的得分片段,设置到高亮显示的的实例对象中。

6、通过分词器获取TokenStream令牌流对象

7、通过令牌和原有的片段,去拿高亮展示后的片段

    /**
     * 测试高亮
     * 
     * @throws Exception
     */
    @Test
    public void testHeight() throws Exception {
        IndexReader reader = DirectoryReader.open(dir);
        IndexSearcher searcher = new IndexSearcher(reader);

        SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer();
        QueryParser parser = new QueryParser("desc", analyzer);
        // Query query = parser.parse("南京文化");
        Query query = parser.parse("南京文明");
        TopDocs hits = searcher.search(query, 100);

        // 查询得分项
        QueryScorer queryScorer = new QueryScorer(query);
        // 得分项对应的内容片段
        SimpleSpanFragmenter fragmenter = new SimpleSpanFragmenter(queryScorer);
        // 高亮显示的样式
        SimpleHTMLFormatter htmlFormatter = new SimpleHTMLFormatter("<span color='red'><b>", "</b></span>");
        // 高亮显示对象
        Highlighter highlighter = new Highlighter(htmlFormatter, queryScorer);
        // 设置需要高亮显示对应的内容片段
        highlighter.setTextFragmenter(fragmenter);

        for (ScoreDoc scoreDoc : hits.scoreDocs) {
            Document doc = searcher.doc(scoreDoc.doc);
            String desc = doc.get("desc");
            if (desc != null) {
                // tokenstream是从doucment的域(field)中抽取的一个个分词而组成的一个数据流,用于分词。
                TokenStream tokenStream = analyzer.tokenStream("desc", new StringReader(desc));
                System.out.println("高亮显示的片段:" + highlighter.getBestFragment(tokenStream, desc));
            }
            System.out.println("所有内容:" + desc);
        }

    }

Lucene自定义过滤

1. Query与Filter同异

  Lucene中查询(Query)和过滤(Filter)有相似之处,查询能处理的,过滤也可以完成。不同之处在于查询时带有评分操作,返回的结果集有相关性评分,而过滤返回的结果集没有相关性评分,即返回结果是无排序的。

2. Filter类结构图


CachingWrapperFilter、FileCacheRangeFilter和FileCacheTermFilter是附带缓存的过滤器.

3. 过滤器基本使用


(1) TermRangeFilter

           特定项范围过滤器,如“a-m”或者“o-z".

TermRangeFilter filter = new TermRangeFilter(field,new BytesRef("h"),new BytesRef("h"),true,true);
TopDocs docs = searcher.search(new MatchAllDocsQuery(),filter,10);


(2)NumericRangeFilter
           数值范围过滤器

NumericRangeFilter<Double> filter=NumericRangeFilter.newDoubleRange(field, 10D, 40D, true, false);
TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),filter,10);


(3) FieldCacheRangeFilter
         域缓存范围过滤器

Filter filter=FieldCacheRangeFilter.newDoubleRange(field, 20D, 50D, true, true);  
TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),filter,10);


(4) FieldCacheTermsFilter
       域缓存过滤特定项过滤器

Filter filter=new FieldCacheTermsFilter(field, new String[]{"技术","社会"});   
TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),filter,10);


(5) QueryWrapperFilter
      使用 QueryWrapperFilter类包装一个query
 

QueryWrapperFilter  filter=new QueryWrapperFilter(new TermQuery(new Term(field, "技术")));  
TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),filter,10);


4.自定义过滤器
      自定义过滤器MyCustomFilter,继承Filter类即可。参考:https://www.jianshu.com/p/92723757f4a7
 

参考:

Lucene的索引详解

Lucene介绍与入门使用

Lucene入门+实现

lucene中的各种Query及其使用

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值