摘要: 关于过滤方面的知识,也就是Filter,如果了解Solr的朋友们,肯定都会知道Solr里面fq这个参数,这个参数的作用其实就是lucene里面的过滤,对一些q参数查询的结果集,做过滤或者限制返回一些我们需要的内容,可以理解成缩小搜索空间的一种策略。

先介绍下查询与过滤的区别和联系,其实查询(各种Query)和过滤(各种Filter)之间非常相似,可以这样说只要用Query能完成的事,用过滤也都可以完成,它们之间可以相互转换,最大的区别就是使用过滤返回的结果集不带评分操作,而使用Query返回的结果都是带相关性评分的,所以当我们如果有一些跟评分操作没有关系的业务,优先使用Filter操作,将会获取更好的性能,其实这也是Solr里面的q参数跟fq参数的区别。

下面,开始进入正题,在这之前,老生常谈的先来了解一下Lucene里面有关于Filter的整体知识 

下面,我们来看下具体的在代码里怎么实现,先来看下我们的测试数据 

id        score        bookname    ename        type            price        date
1 1 飘渺之旅 pmzl 小说 52.23 201005
2 1 三国演义 sgyy 小说 36.13 201207
3 1 数据库实战 sjksz 技术 77.13 200811
4 1 编程宝典 bcbd 技术 100.3 200501
5 1 职场关系论 zcgxl 职场 36.59 200501
6 1 健康生活 jksh 生活 20.47 200008
7 1 看清本质 kqbz 社会 10.37 201004
8 1 编程,编程 bcbc 社会 10.37 201004

核心代码

//使用过滤器   最后一个为true时包含边界部分,为false时不包含边界部分
//倒数第二个为true时,包含查询边界,为false时不包含
TermRangeFilter filter=new TermRangeFilter("ename", new BytesRef("h"), new BytesRef("n"), true, true);
TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),filter,10000);//默认无排序方式

输出结果

6        1        健康生活        jksh        生活        20.47        200008
7 1 看清本质 kqbz 社会 10.37 201004

核心代码 

NumericRangeFilter<Double> filter=NumericRangeFilter.newDoubleRange("price", 10D, 40D, true, false);
TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),filter,10000);//默认无排序方式

输出结果

2        1        三国演义        sgyy        小说        36.13        201207
5 1 职场关系论 zcgxl 职场 36.59 200501
6 1 健康生活 jksh 生活 20.47 200008
7 1 看清本质 kqbz 社会 10.37 201004
8 1 编程,编程 bcbc 社会 10.37 201004

核心代码

 
//使用缓存过滤
Filter filter=FieldCacheRangeFilter.newDoubleRange("price", 20D, 50D, true, true);
TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),filter,10000);//默认无排序方式

输出结果

2        1        三国演义        sgyy        小说        36.13        201207
5 1 职场关系论 zcgxl 职场 36.59 200501
6 1 健康生活 jksh 生活 20.47 200008

核心代码

// 缓存域过滤特定的类别
Filter filter=new FieldCacheTermsFilter("type", new String[]{"技术","社会"});
TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),filter,10000);//默认无排序方式

输出结果

3        1        数据库实战        sjksz        技术        77.13        200811
4 1 编程宝典 bcbd 技术 100.3 200501
7 1 看清本质 kqbz 社会 10.37 201004
8 1 编程,编程 bcbc 社会 10.37 201004

核心代码

//使用QueryWrapperFilter类包装一个Query
QueryWrapperFilter filter=new QueryWrapperFilter(new TermQuery(new Term("type", "技术")));
TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),filter,10000);//默认无排序方式

输出结果

//使用QueryWrapperFilter类包装一个Query
QueryWrapperFilter filter=new QueryWrapperFilter(new TermQuery(new Term("type", "技术")));
TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),filter,10000);//默认无排序方式

最后我来看下,如何继承Filter基类,来定制我们自己的filter,自定义的Filter,虽然某些时候,功能很强大灵活,但是有几个缺点,我们的了解1,保证是内容不重复的字段,例如主键,如果重复,默认返回第一个作为结果集显示2,保证不能被分词的内容,如果是分词的字段,则可能会出现一些不正确的结果。 
自定义Filter类

package com.sanjiesanxian.test;

import java.io.IOException;
import java.util.BitSet; import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.index.DocsEnum;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.Filter;
import org.apache.lucene.util.AttributeSource;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.DocIdBitSet;
import org.apache.lucene.util.FixedBitSet;
import org.apache.lucene.util.OpenBitSet; /***
*^_^ ^_^ ^_^
* QQ交流探讨群:324714439
* 自定义过滤器
* @author 三劫散仙
* */
public class MyCustomFilter extends Filter{ public MyCustomFilter() {
// TODO Auto-generated constructor stub
} private String[] terms;//限制返回的数据字典
public MyCustomFilter(String ...terms) {
// TODO Auto-generated constructor stub
this.terms=terms;
}
@Override
public DocIdSet getDocIdSet(AtomicReaderContext arg0, Bits arg1)
throws IOException {
FixedBitSet bits=new FixedBitSet(arg0.reader().maxDoc()) ;//获取没有所有的docid包括未删除的
int base=arg0.docBase;//段的相对基数,保证多个段时相对位置正确
//int limit=base+arg0.reader().maxDoc();//计算最大限制值
for(String s:terms){
DocsEnum doc=arg0.reader().termDocsEnum(new Term("id", s));//必须是唯一的不重复
//保证是单个不重复的term,如果重复的话,默认会取第一个作为返回结果集,分词后的term也不适用自定义term
if(doc.nextDoc()!=-1){
bits.set(doc.docID());//对付符合条件约束的docid循环添加到bits里面
}
}
return bits;
}
}

测试查询代码

 MyCustomFilter filter=new MyCustomFilter("3","5","2");//随意指定1之多个需要过滤的项
TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),filter,10000);

输出结果

2        1        三国演义        sgyy        小说        36.13        201207
3 1 数据库实战 sjksz 技术 77.13 200811
5 1 职场关系论 zcgxl 职场 36.59 200501

自定义过滤器虽然有缺点,但是某些场景下却能发挥很灵活的作用,特别是对没有分词的字段进行过滤操作。

转自:https://my.oschina.net/MrMichael/blog/220787

lucene 过滤结果的更多相关文章

  1. 1.7.4 Query Syntax and Parsing

    1. 查询语法和解析 这部分主要说明了如何指定被使用的查询解析器.同样描述了主查询解析器的支持的语法和功能.同时还描述了在特定环境下使用的其他查询解析器.这里有一些普通查询解析器都能使用的参数,将会在 ...

  2. 【lucene系列学习四】使用IKAnalyzer分词器实现敏感词和停用词过滤

    Lucene自带的中文分词器SmartChineseAnalyzer不太好扩展,于是我用了IKAnalyzer来进行敏感词和停用词的过滤. 首先,下载IKAnalyzer,我下载了 然后,由于IKAn ...

  3. lucene整理3 -- 排序、过滤、分词器

    1.    排序 1.1. Sort类 public Sort() public Sort(String field) public Sort(String field,Boolean reverse ...

  4. lucene 范围过滤

    Lucene里面有关于Filter的整体知识 下面,我们来看下具体的在代码里怎么实现,先来看下我们的测试数据 Java代码    id      score       bookname    ena ...

  5. lucene查询索引库、分页、过滤、排序、高亮

    2.查询索引库 插入测试数据 xx.xx. index. ArticleIndex @Test public void testCreateIndexBatch() throws Exception{ ...

  6. lucene自定义过滤器

    先介绍下查询与过滤的区别和联系,其实查询(各种Query)和过滤(各种Filter)之间非常相似,可以这样说只要用Query能完成的事,用过滤也都可以完成,它们之间可以相互转换,最大的区别就是使用过滤 ...

  7. MySQL和Lucene索引对比分析

    MySQL和Lucene都可以对数据构建索引并通过索引查询数据,一个是关系型数据库,一个是构建搜索引擎(Solr.ElasticSearch)的核心类库.两者的索引(index)有什么区别呢?以前写过 ...

  8. Lucene系列-FieldCache

    域缓存,加载所有文档中某个特定域的值到内存,便于随机存取该域值. 用途及使用场景 当用户需要访问各文档中某个域的值时,IndexSearcher.doc(docId)获得Document的所有域值,但 ...

  9. Apache Lucene(全文检索引擎)—分词器

    目录 返回目录:http://www.cnblogs.com/hanyinglong/p/5464604.html 本项目Demo已上传GitHub,欢迎大家fork下载学习:https://gith ...

随机推荐

  1. 列车时刻表查询 jqm/ajax/xml

    <!doctype html><html lang="en"><head> <meta charset="UTF-8" ...

  2. Hbase之校验指定数据是否存在

    import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; impo ...

  3. Python核心编程-细节

    直接从六张开始看看书里有什么. cmp() len() max() and min() sorted() and reversed() enumerate() and zip() sum() list ...

  4. 线性表 - 从零开始实现by C++

    参考链接:数据结构探险之线性表篇     线性表

  5. sizeof和strlen()的区别

    二者有本质上的区别 从定义可以知道sizeof只是一个operator,而strlen()则是定义一个定义在<string.h>中的函数;所以sizeof(string)是在计算strin ...

  6. C/C++中堆与栈

    本文介绍C/C++中堆,栈及静态数据区.   五大内存分区 在C++中,内存分成5个区,他们分别是堆.栈.自由存储区.全局/静态存储区和常量存储区.下面分别来介绍: 栈,就是那些由编译器在需要的时候分 ...

  7. java 多线程1

    进程: 线程: 多线程: 假象:只是CPU在做快速的切换 多线程的好处: 1.解决了一个进程里面可以同时运行多个任务(执行路径) 2.提高资源利用率,而不是效率. 多线程的弊端: 1.降低了一个进程里 ...

  8. 猫都能学会的Unity3D Shader入门指南

    https://onevcat.com/2013/07/shader-tutorial-1/ https://onevcat.com/2013/08/shader-tutorial-2/

  9. 屏幕输出VS文件输出

     问题1:我们在编写程序时经常需要数一些数据到屏幕,来查看我们的结果是否正确,虽然直接输出到屏幕,查看起来呢很方便,但当数据量很大时,需要耗费大量的时间.于是我们想到能不能通过输出到文件来减少时间 ...

  10. python 练习 3

    #!/usr/bin/python # -*- coding: utf-8 -*- def z94(): #斐波那契数列 def filie(x): a,b,t=1,1,0 if x==1 or x= ...