全面解剖 Solr query 到lucene query

全面解剖 Solr query 到lucene query

(2013-03-26 14:46:41)

转载

标签:

杂谈

分类: 搜索技术

围绕从顶之下,从粗到西的关系认识solr 查询流程和实现细节。最低下定位到queryparse的实现。整个过程围绕信息检索这一思路展开,而不是工程实现来看这个问题。目的从整体结构上认识查询这一块的抽象。这样有具体需求的时候,可以知晓参照按个query、从哪个点注入系统中比较省事,而无需侵入solr、lucene底层。

另外一方面,围绕这个流程看solr在lucene之上的封装,从而一旦完全基于lucene实现自己的结构时候,也可以做到扬长避短,做到有参照、有改进,大大降低细节面临的风险。

1.Solr&Lucene query 执行流程、关系

2 如何扩展Query

3.QueryParse语法树

--》执行流程关系

Request--EmbededServer--solrCore---StandardRequestHandler--solrRequestParser---RequestHandlerBase---

----SearchHandler----QueryCompoment---SolrIndexSearcher

全面解剖 <wbr>Solr <wbr>query <wbr>到lucene <wbr>query

流程画的不够严谨,争取将相关核心流程展示出来。有两个点需要注意:solrcore、searchcomponent (querycomponet),

--》简要描述模块流程如下

全面解剖 <wbr>Solr <wbr>query <wbr>到lucene <wbr>query

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

全面解剖 <wbr>Solr <wbr>query <wbr>到lucene <wbr>query

全面解剖 <wbr>Solr <wbr>query <wbr>到lucene <wbr>query
--》如何扩展Query

1)扩展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。 

(2)另外一种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">4
  

 name="endTier">19


  

查询构造

      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 中文预料库机器学习、新词发现、词性分析等等。据了解,很多有司都是在他的基础上扩展、改写的。

猜你喜欢

转载自blog.csdn.net/lusic01/article/details/81207237
今日推荐