Solr 函数查询(FunctionQuery)原理分析
来源:互联网 发布:中国人没有信仰 知乎 编辑:程序博客网 时间:2024/05/16 17:47
此文原创,转载请说明出处:http://ronxin999.blog.163.com/blog/static/4221792020111013131992/
solr 函数查询有4种方式来实现,这个在solr的wiki里描述的比较清楚,但是这个东西到底是个什么意思,原理是什么,solr wiki并没有说的很清楚,很多朋友也是对此一头雾水,现在我经过一定时间的调试,总结了点经验,写下来,和喜欢solr的朋友共勉。
这里说其中的一种,也是最诡异的一种实现方法:_val_
举个查询例子为q=title:hadoop _val_:count 这里顺便说下hadoop和_val_中间的空格,由于solr默认是OR,所以这里是一个or组合的booleanQuery,如果是q=title:hadoop AND _val_:count 则是一个有AND组合的BooleanQuery查询。
title和count都是solr配置文件schema.xml里面的一个field,title:hadoop很明细,搜索文档的field值包含hadoop的文档。假如
索引库里总共有5个document 1,2,3,4,5,其中doucument 2,5的field包含hadoop值,那title:hadoop搜索到2,5两个document,
_val_:count
由于_val_代表的是functionQuery,由于我们索引库里的每个document都包含count域。所以solr会把所有库里的5个document
ID取到,其实solr是直接读reader.maxDoc(),这里值为5,
由于是 OR,solr底层luence会对两者坐并集,然后对并集的doc ID 打分。关键就在这个打分,也是_val_:count的体现。
由于文档2,5在两个集合里都出现,所以,document 2和5的得分也是两个得分之和。title:hadoop返回的文档2和5的得分就是luence的评分公式计算出来的,而_val_:count是有FunctionQuery的内部类FunctionWeight来计算的,不过FunctionWeight计算权重时,idf的值为1,由FunctionWeight计算的值再乘以该document域count的值,所以整个的查询结果是5个document,但是2,5这个两个文档的得分会很高。但跟这个两个文档的count域的值有关。
同样如果是q=title:hadoop AND _val_:count 逻辑于查询,那结果只有两个文档,因为luence会对其期交集,同样的是也会把相同的文档的得分相加。
顺便再说下,如果_val_:3这也,后面直接跟数据,solr就不要到索引库里去取指定域如上面count域的值了,而是直接为3,如果是跟field,solr会用到fieldCache,把该域的值取出来放到fieldCache中,下次取就不要再读索引库了。
这里再讲下_val_:rod(count)也就是_val_后面跟函数的情况。
这里用我自己自定义的函数代码如下:
public class MyValueSourceParser extends ValueSourceParser {
public MyValueSourceParser(){
super();
System.out.println("========初始化MyValueSourceParser实例==========");
}
@Override
public ValueSource parse(FunctionQParser fp) throws ParseException {
System.out.println("========开始执行MyValueSourceParser的parse方法==========");
String field = fp.parseId();
//我们这里是要根据域field的值从而可以关联一个得分。我这个Field是字符串形式的。
//StrKeywordsFieldSource 是继承StrFieldSource,solr有什么类型的Filed有相应的ValueSource。
StrKeywordsFieldSource stringFieldSource = new StrKeywordsFieldSource(field);
return stringFieldSource;
}
}
//StrKeywordsFieldSource类的源码如下:
public class StrKeywordsFieldSource extends StrFieldSource {
private static final long serialVersionUID = 1L;
//必须的
public StrKeywordsFieldSource(String field) {
super(field);
// TODO Auto-generated constructor stub
}
/**
* 重写getValues方法,StrFieldSource就是取field对应的值,我们要 根据值再做具体的运算。
* 由于,在函数查询里最终是调用getValues方法来取得结果的,所以我们都要重写getValues方法。
* getValues方法返回的是DocValues ,计算得分是DocValues 的floatVal方法。我们的都要重写。
*/
@Override
public DocValues getValues(Map context, IndexReader reader) throws IOException {
return new StringIndexDocValues(this, reader, field) {
@Override
protected String toTerm(String readableValue) {
return readableValue;
}
@Override
public float floatVal(int doc) {
String isbn = strVal(doc);
System.out.println("doc["+doc+"] isbn value is ["+isbn+"]");
if("hadoop".equals(isbn)){
return 100f;
}else if("action".equals(isbn)){
return 10f;
}else{
return 1f;
}
}
@Override
public int intVal(int doc) {
int ord=order[doc];
return ord;
}
@Override
public long longVal(int doc) {
return (long)intVal(doc);
}
@Override
public double doubleVal(int doc) {
return (double)intVal(doc);
}
@Override
public String strVal(int doc) {
int ord=order[doc];
return lookup[ord];
}
@Override
public String toString(int doc) {
return description() + '=' + strVal(doc);
}
};
}
}
自己写的函数查询要添加到solrconfig.xml配置文件才能生效。配置文件修改如下:
//函数名为:testfunc
<valueSourceParser name="testfunc"
class="com.solr.parse.plugin.MyValueSourceParser" />
现在我们可以通过_val_:"testfunc(keywords)"来函数查询了。记住函数一定要用""引起来。
比如我查询标题有hadoop的文档为 q=title:hadoop AND _val_:"testfunc(keywords)"这样就查到包含hadoop的文档的keywords域的值可以改变打分。如果keywords域就一个值还,如果keywords域有多个term,那就有多个值。那用那个呢,还有如果文档比较少,但是keywords域包含的词有很多这个又是怎么弄的。经过测试。可以回答上面两个问题。
1 solr会把所有文档的keywords域的Term放在一个枚举里面,这所有的Term是按字典排好序的。也就是取的时候是按字典顺序 取的。假如我查询title域包含hadoop的文件就3个,而我这3个文档title域包含6个Term,那Solr只取按字典排好序的前3个Term.
讲了这么多,再总结下,其实solr函数查询关键取出所有的文档,在luence的打分基础上乘以函数计算的值作为得分。
0 0
- Solr 函数查询(FunctionQuery)原理分析
- solr之functionQuery(函数查询)
- solr之functionQuery(函数查询)
- Solr --- 函数查询(FunctionQuery)
- functionQuery(函数查询)
- SOLR中实现自定义评分函数FunctionQuery
- 如何实现自定义的solr FunctionQuery
- Solr 6.0 学习(十六)FunctionQuery
- Solr区间查询背后原理
- Solr查询过程源码分析
- Solr查询过程源码分析
- Solr Analysis And Solr Query -- Solr分析以及查询
- solr MoreLikeThis的原理分析
- Solr Dismax查询解析器-深入分析
- Solr空间索引原理及源码分析
- Solr空间搜索原理分析与实践
- 转载:solr MoreLikeThis的原理分析
- solr查询参数、语法、函数总结
- python 除法和乘方
- NSArray 与 NSMutableArray 常用方法
- android 一个问题
- Longest Substring Without Repeating Characters
- iOS开发动画(Animation)图片360度不停旋转
- Solr 函数查询(FunctionQuery)原理分析
- 简单时间编程
- Android 那些你所不知道的Bitmap对象详解
- 第15周上机实践项目1——打入“内部”寻“内幕”
- 添加第三方类库造成的linker command failed with exit code 1 (use -v to see invocation)的错误调试
- 山地速降,玩的就是心跳
- Chrome多进程调试
- shell脚本中简单的函数示例
- Internet起源