`
suichangkele
  • 浏览: 193124 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

实现得分的PrefixQuery

阅读更多

(先声明一下,我使用的lucene的版本是lucene4.7.2)

在lucene中,有一种类型的query叫做MultiTermQuery,故名思议,他是要涉及到很多个term的query,比如我们常用的WildcardQuery、FuzzyQuery、PrefixQuery、TermRangeQuery、NumericRangeQuery等,他们都是需要按照一个或者多个term按照一定的逻辑找到多个term,然后再重写由找到的这些term形成的TermQuery进入一个新的Query(比如BooleanQuery、或者ConstantScoreQuery),但是有个一指的注意的地方是:有些MultiTermQuery是不得分的,也就是在返回的时候不会按照得分排序,比如PrefixQuery,的不得分是由每个MultiTermQuery使用的rewriteMethod指定,也就是由重写规则指定。本文的目的不在于讨论重写规则,而是想实现一个可以得分的PrefixQuery(业务场景是我们要使用PrefixQuery做搜索框中提示词的排序,所以必须实现得分)。

 

实现原理很简单,在指定重写规则的时候将重写规则指定为得分的规则(当然这里涉及到重写规则的实现,这里本文不讨论),在org.apache.lucene.search.MultiTermQuery类中含有SCORING_BOOLEAN_QUERY_REWRITE这个重写规则从他的名字中就可以理解是封装为一个BooleanQuery,并且计算分数。他的逻辑很简单,将搜索到的多个termQuery封装成一个booleanQuery,每一个termQuery都是optional的,也就是对多个termQuery取并集。但是Booleanquery有个需要注意的地方,他不能有太多的clause,不然会报错,默认是1024个,所以我们需要修改这个值,做到这里就算是完成了。我的代码如下:

/**
 * 由于solr自带的PrefixQuery是不得分的,不能满足提示词的排序要求,所以重写这个query.
 */
public class ScoredPrefixQuery extends PrefixQuery {

	//从词典表中得到的term的限制,用于做测试的,实际中不用
	private int limit = -1; 
	
	static{
		BooleanQuery.setMaxClauseCount(Integer.MAX_VALUE);//设置BooleanQuery的最多的子query的个数为Integer.MAX_VALUE。
	}
	
	public ScoredPrefixQuery(Term prefix) {
		super(prefix);
		//重置重写规则,使用得分的booleanQuery,此处存在的问题是可能会发生BooleanQuery.TooManyClauses,所以要在得到term的时候需要做限制
		setRewriteMethod(org.apache.lucene.search.MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE);
	}
	/**
         * 从词典表中得到前缀匹配的term的方法
         */
	@Override
	public TermsEnum getTermsEnum(Terms terms, AttributeSource atts) throws IOException {
		 TermsEnum tenum = terms.iterator(null);
		 if (getPrefix().bytes().length == 0) {
		      // no prefix -- match all terms for this field:
		     return tenum;
		 }
		 return new PrefixTermsEnum(tenum, getPrefix().bytes()) {
			 int already = 0;
			 final int termLimit =  limit==-1?BooleanQuery.getMaxClauseCount():limit;//设置limit只是用于做测试的。
			 
			 @Override
			public BytesRef next() throws IOException {
				
				BytesRef ref = super.next();//先调用父类方法,即从词典表中读取,
				if(ref == null){//如果真的读完了,就返回null。
					return null;
				}else{//没有读取完,则判断是否已经读取了太多的term
					//最多的BooleanClause的个数
					if(already++ < termLimit){//一个前缀最多从词典表中得到booleanquery的MaxClause个,这样就不会报错了。
						return ref;
					}
					return null;
				}
			}
		 };
	}
	
	public int getLimit() {
		return limit;
	}
	
	//做测试用的
	public void setLimit(int limit) {
		this.limit = limit;
	}
	
//这个测试的前提是我们在索引中仅仅保存了只有id域的100个document,id为从0-99,省略了建立索引的代码。
	public static void main(String[] args) throws IOException {
		
		IndexReader reader = DirectoryReader.open(getDirectory());
		
		IndexSearcher search = new IndexSearcher(reader);
		ScoredPrefixQuery q = new ScoredPrefixQuery(new Term("id","1"));//这一行和下面的PrefixQuery q 这一行是区分的,如果使用这一行则只会搜到3个,并且得分不是1.0f,也就是是得分的。
		q.setLimit(3);//设置最多为3个。
		
//		PrefixQuery q = new PrefixQuery(new Term("id", "1"));//如果使用lucene中默认使用的PrefixQuery则会搜到11个,并且得分都是1.0f,也就是没有得分。
		
		TopDocs td = search.search(q, 100);
		for(ScoreDoc sd:td.scoreDocs){
			System.out.println(sd.score);
		}
		System.out.println(td.scoreDocs.length);
		
	}	
}

 

这样就完成了得分的前缀匹配的query,如果要在solr中使用,还需要自己定义queryparser的插件,这个留在以后再写博客。

 

 

 

分享到:
评论

相关推荐

    PreFixFilterQuery.java

    ilter:所有的过滤器都在服务端生效,以保证被过滤掉的数据不会被传送到客户端 •过滤器是在HBase服务器端上执行判断操作 •过滤器可以应用到行键(RowFilter),列限定符(QualifierFilter)或者数据值...

    【分享:lucene学习资料】---<下载不扣分,回帖加1分,欢迎下载,童叟无欺>

    2&gt; 全文检索的实现机制 【1】lucene学习笔记的目录如下 1. 概述 3 2. lucene 的包结构 3 3. 索引文件格式 3 4. lucene中主要的类 4 4.1. Document文档类 4 4.1.1. 常用方法 4 4.1.2. 示例 4 4.2. Field字段类 4 ...

    Lucene 3.6 学习笔记

    (3) 前缀查询(PrefixQuery) 11 (4) 通配符查询(WildcardQuery) 11 (5) 多条件查询(BooleanQuery) 12 (6) 短语查询(PhraseQuery) 12 (7) 模糊查询(FuzzyQuery) 12 3.3 QueryParser 13 (1) 创建QueryParser ...

    InformationRetrievalWithLucene

    使用Lucene实现一个IR系统 功能: 索引:1.创建索引 2.delete index 3.add index 4.update index 搜索: 1.termQuery 2.multiFieldQuery 3.booleanQuery 4.prefixQuery 5.phraseQuery 6.multiPhraseQuery 7....

    前18大旋转修整器企业占据全球87%的市场份额.docx

    前18大旋转修整器企业占据全球87%的市场份额

    Planet-SkySat-Imagery-Product-Specification-Jan2020.pdf

    SKYSAT IMAGERY PRODUCT SPECIFICATION PLANET.COM VIDEO Full motion videos are collected between 30 and 120 seconds by a single camera from any of the active SkySats. Videos are collected using only the Panchromatic half of the camera, hence all videos are PAN only. Videos are packaged and delivered with a video mpeg-4 file, plus all image frames with accompanying video metadata and a frame index file (reference Product Types below)

    Screenshot_20240506_133458_com.netease.yhtj.vivo.jpg

    Screenshot_20240506_133458_com.netease.yhtj.vivo.jpg

    2019年A~F题特等奖论文合集.pdf

    大学生,数学建模,美国大学生数学建模竞赛,MCM/ICM,历年美赛特等奖O奖论文

    雷达物位变送器安装和操作手册

    雷达物位变送器安装和操作手册

    node-v11.6.0-linux-armv7l.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    Python3实现快速排序(源代码)

    快速排序是一种基于分治策略的排序算法,通过选择一个基准元素,将待排序的数组划分为两个子数组,一个包含所有小于基准的元素,另一个包含所有大于基准的元素,然后递归地对这两个子数组进行快速排序。快速排序在平均情况下具有O(n log n)的时间复杂度,是一种非常高效的排序算法。然而,在最坏情况下,当输入数据已经有序或接近有序时,快速排序的性能会退化为O(n^2)。此外,快速排序是不稳定的排序算法,即相等的元素可能在排序过程中改变相对位置。尽管如此,快速排序仍然因其高效的平均性能而在实际应用中广泛使用。在Python3中,可以通过递归或迭代的方式实现快速排序算法,但为了避免额外的空间开销,通常会采用原地排序的方式来实现。

    毕业课设基于51单片机的出租车计价器(昼夜)

    【作品名称】:基于51单片机的出租车计价器(昼夜) 含(程序、仿真图、流程图、原理图) 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 出租车计价器: 1、不同情况具有不同的收费标准,具有白天和夜晚不同的计价能力 2、能进行手动修改单价 3、具有数据的复位功能(起步价,起步公里数,里程单价,白天晚上不一样) 4、能够在掉电的情况下存储单价等数据 5、步进电机模拟里程,一圈表示一里路

    2024年中国API 11P往复式气体压缩机行业研究报告.docx

    2024年中国API 11P往复式气体压缩机行业研究报告

    Windows 10系统上安装和配置Tomcat的步骤

    附件是Windows 10系统上安装和配置Tomcat的步骤,文件绿色安全,请大家放心下载,仅供交流学习使用,无任何商业目的!

    广东工业大学《计算网络A》实验报告期末考试试题回忆版.doc

    此试题是考试后回忆版本,你会发现是惊喜。恭喜你考个好成绩。

    数据库+人大金仓+Linux系统安装

    数据库+人大金仓+Linux系统安装

    2023年美赛特等奖论文-C-2309397-解密.pdf

    大学生,数学建模,美国大学生数学建模竞赛,MCM/ICM,2023年美赛特等奖O奖论文

    opencv-python-4.5.4.60-cp36-cp36m-win-amd64.whl

    opencv-python-4.5.4.60-cp36-cp36m-win-amd64.whl

    减肥管理,全球前10强生产商排名及市场份额.docx

    减肥管理,全球前10强生产商排名及市场份额

    上海大学大学生创新创业训练计划申请书(创新训练项目).doc

    内容概要:《上海大学大学生创新创业训练计划申请书(创新训练项目)》是用于申请参加上海大学的大学生创新创业训练计划的申请书,旨在帮助学生提出创新项目计划,获得培训和支持,促进学生创新创业能力的提升。 适用人群:适合上海大学的在校大学生,特别是对创新创业感兴趣、有创新想法和创业计划的学生,希望通过该计划获得指导和资源支持,实现自己的创业梦想。 使用场景及目标:申请书的使用场景是为了参加上海大学的大学生创新创业训练计划,目标是通过提交详细的创新项目计划,获得评审通过并获得培训、指导和资金支持,从而推动学生的创新创业实践和能力提升。 其他说明:申请书应包括清晰的创新项目描述、项目可行性分析、预期目标和计划、团队介绍等内容,以展现学生的创新能力和项目潜力。申请书的撰写需要认真准备,体现出学生对创新创业的热情和才华,以提高申请成功的机会。

Global site tag (gtag.js) - Google Analytics