围绕从顶之下,从粗到西的关系认识solr 查询流程和实现细节。最低下定位到queryparse的实现。整个过程围绕信息检索这一思路展开,而不是工程实现来看这个问题。目的从整体结构上认识查询这一块的抽象。这样有具体需求的时候,可以知晓参照按个query、从哪个点注入系统中比较省事,而无需侵入solr、lucene底层。
围绕这个流程看solr在lucene之上的封装,从而一旦完全基于lucene实现自己的结构时候,也可以做到扬长避短,做到有参照、有改进,大大降低细节面临的风险。
1.Solr&Lucene query 执行流程、关系
2 如何扩展Query
3.QueryParse语法树
执行流程关系
流程画的不够严谨,争取将相关核心流程展示出来。有两个点需要注意:solrcore、searchcomponent (querycomponet),
简要描述模块流程如下
QParser是Core作用域,不同的searchHandler都是可以调用的,
searchComponent是searchHandler作用域,默认走StandardRequestHandler,走默认的searchComponent 链。也就是说不同的searchHandler可以走不同的searchComponent。每个searchHandler对于自己的一个路径。
Lucene的排序体系包含了Query、Weight、Score、Similarity几个不同的类
文档匹配阶段主要调用Searcher对象的search方法,在search方法内部,通过直接或者间接调用
Search(Weight weight,Filter filter,Collector collector). 使用search的时候会创建Weight对象,
Weight对象会创建一个score对象,score对象来进行score函数的调用,并将结果保存在Collector对象中。
Scorer 用一个匿名类Collector来收集满足TermQuery的doc
Scorer的代码也表明, 它在遍历所有合法文档时,背后的查询动作是在穷举一个数组:doc[], 而这个数组的来源就是TermDocs.所以高命中耗时。
Solr&Lucene已经提供的成熟的各种query
之所以贴出这个简图,目的的是想说明:lucene solr已经实现的query可以说100%能满足你的需要,没有必要折腾搞个新的玩意,lucene 从1.9到现在,query的东西是最稳当的、变更最少的。这是query本身的特征决定的。即使索引结构、引擎如何变,而查询需求、查询规则不变。
已经实现的query,有如下特征,不一定合理,仅供参考
偏向基本的:termquery booleanquery、Functionquery
偏向性能的:MultiTermQuery序列
偏向排序质量的:phrasequery一览
偏向新场景的:spatialquery sqlquery relationquery
如何扩展Query
扩展Qp:构建相应的Query
abstract class QParserPlugin implements NamedListInitializedPlugin {
public abstract QParser createParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req);
public class TermQParserPlugin extends QParserPlugin {
@Override
publicQParser createParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {
returnnewQParser(qstr, localParams, params, req) {
@Override
publicQuery parse() {
String fname = localParams.get(QueryParsing.F);
FieldType ft = req.getSchema().getFieldTypeNoEx(fname);
String val = localParams.get(QueryParsing.V);
BytesRef term = new BytesRef();
if (ft != null) {
ft.readableToIndexed(val, term);
} else {
term.copyChars(val);
}
return new TermQuery(new Term(fname, term));
}
};
}
这里指扩展QP,扩展的QP 配置在solrconfig.xml中,执行查询的时候指定对于的qp 名称既可以加载相应的QP。
另外一种QP扩展,同时扩展排序规则---filter类型query
public interface PostFilter extends ExtendedQuery {
class FunctionRangeQuery extends SolrConstantScoreQuery implements PostFilter {
final ValueSourceRangeFilter rangeFilt;
然后在SolrIndexSearcher getDocSet中会根据ExtendedQuery 或者WrappedQuery做调用各自的query 和重写的filter
eg:
solconfig.xml中定义 // 定义完整信息丢失了,只能看个大意了
<name="tier" class="com.taobao.tsearcher.qp.CartesianTierQParserPlugin">
<name="geoHash">store_latlon
<name="startTier">
<name="endTier">
查询构造
query.setQuery("title:广*");
query.addFilterQuery("{!tier x=30.757575 y=105.70757 dist=10}");
基本扩展原理与solr41中的SpatialFilterQParsePlugin\FunctionQParserPlugin 类似,看懂就完全明白如何注入自己的query了,本质是通过本地参数来解析获取对于注入的qp。
2 SQLQuery
类Sql 语句-->词法(字符串检测)、语法(正则表示规则校验逻辑)分析,语法树翻译对于模板格式下的对应solr查询语法--> solrquery优化
直接编写Queryparser.jj.
第一步对QueryParse.jj 做词法扩展、语法扩展,
第二步 javacc 编辑扩展后的QueryParser.jj,生成对应的词法、语法分析程序。
第三步 针对sql query 提供相应的query接口。
3 RelationQuery
1.关系模型设计
2.工程实现设计
[1]关于模型初步的思考
基于词的关联,任务,收集同义词、基于上下文场景的关联扩展。
(1-1)同意扩展
文字与数字转换:一百 /100; 一九四九/1949
直接同义词扩展:一脉相传/一脉相承/ 一马当先/一马领先
一部分是分词处理,一部分是queryparse处理。
(1-2) 关联扩展 淘宝/杭州/女装。需要分析搜索query自动提取
(2) PageRank & PeopleRank
针对item设计属性,按照属性计算得分,排序按照离线模型执行sort
(3) VSM
针对item提取属性值,建索引将属性内容index起来,查询的时候也传入相关属性值,按照多属性值得AND求交集,然后对结果按照向量夹角计算得分,问题转化为直接lucene当前默认模型。
(4)Shape
每个item定义高纬度坐标,采取类似地理搜索的模型,按照shape做结果集的过滤。
[2]实现思路:
参照上面的分析以filter的形式,改下qparse和 docidset以及score
Qparse、Filter 、sort的扩展,可以理解为FunctionQuery的特例化。
Eg:shape区间交集
将关系映射到平面区间,关系的交集转为平面的交集,从而转义为shape过滤。
Object={ item1,item2,item3} AND object={item4,item5,item6}
Eg:sort
结果按照关系维度参数,做类似functionquery的关系模型距离计算。
Eg:sort
是向量空间模型,输入多个条件,按照向量模型计算得分。
其他高级处理,就是机器学习能自动化相关参数、流程。这一块还没有深入,所以还没有相关经验。
lucene Queryparse底层
请参照下面这个链接
http://www.cnblogs.com/forfuture1978/archive/2010/05/08/1730200.html
这里面的分析依然是强大的,尽管在4.*序列有局部调整,单对分析原理、实现细节非常有帮助。
Javacc 基础上扩展qp的详细分析文档见附件上面的链接
javacc本质上和我之前基于solrflux扩展sql支持hl、 facet一样的。
http://blog.sina.com.cn/s/blog_4d58e3c001013wka.html solrflux的我之前总结的文档。
相信看完这个文档,大家一定非常清楚solr语法最终如何转为lucene查询的。如何扩展sql也就一目了然。
不过这需要大家提前知晓:文法、词法分析、语法分析这些基本概念和原理,基本上都是理论的公式、形式化的内容
深入NLP的内容:例如 词法、语法分析,不妨参考下stanford segment parse 中文预料库机器学习、新词发现、词性分析等等。据了解,很多有司都是在他的基础上扩展、改写的。