Lucene简介
一、Lucene 核心API
-
索引过程中的核心类
- Document文档:他是承载数据的实体(他可以集合信息域Field),是一个抽象的概念,一条记录经过索引之后,就是以一个Document的形式存储在索引文件中的。
- Field:Field 索引中的每一个Document对象都包含一个或者多个不同的域(Field),域是由域名(name)和域值(value)对组成,每一个域都包含一段相应的数据信息。
- IndexWriter:索引过程的核心组件。这个类用于创建一个新的索引并且把文档 加到已有的索引中去,也就是写入操作。
- Directroy:是索引的存放位置,是个抽象类。具体的子类提供特定的存储索引的地址。(FSDirectory 将索引存放在指定的磁盘中,RAMDirectory ·将索引存放在内存中。)
- Analyzer:分词器,在文本被索引之前,需要经过分词器处理,他负责从将被索引的文档中提取词汇单元,并剔除剩下的无用信息(停止词汇),分词器十分关键,因为不同的分词器,解析相同的文档结果会有很大的不同。Analyzer是一个抽象类,是所有分词器的基类。
-
搜索过程中的核心类
- IndexSearcher :IndexSearcher 调用它的search方法,用于搜索IndexWriter 所创建的索引。
- Term :Term 使用于搜索的一个基本单元。
- Query : Query Lucene中含有多种查询(Query)子类。它们用于查询条件的限定其中TermQuery 是Lucene提供的最基本的查询类型,也是最简单的,它主要用来匹配在指定的域(Field)中包含了特定项(Term)的文档。
- 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