全面解剖 Solr query 到lucene query

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

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

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

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

2 如何扩展Query

3.QueryParse语法树


执行流程关系

image.png

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


简要描述模块流程如下


image.png

QParserCore作用域,不同的searchHandler都是可以调用的,

searchComponentsearchHandler作用域,默认走StandardRequestHandler,走默认的searchComponent 链。也就是说不同的searchHandler可以走不同的searchComponent。每个searchHandler对于自己的一个路径。

 

Lucene的排序体系包含了QueryWeightScoreSimilarity几个不同的类

文档匹配阶段主要调用Searcher对象的search方法,在search方法内部,通过直接或者间接调用

Search(Weight weight,Filter filter,Collector collector). 使用search的时候会创建Weight对象,

Weight对象会创建一个score对象,score对象来进行score函数的调用,并将结果保存在Collector对象中。

Scorer 用一个匿名类Collector来收集满足TermQuerydoc

Scorer的代码也表明, 它在遍历所有合法文档时,背后的查询动作是在穷举一个数组:doc[], 而这个数组的来源就是TermDocs.所以高命中耗时。


Solr&Lucene已经提供的成熟的各种query

之所以贴出这个简图,目的的是想说明:lucene solr已经实现的query可以说100%能满足你的需要,没有必要折腾搞个新的玩意,lucene 1.9到现在,query的东西是最稳当的、变更最少的。这是query本身的特征决定的。即使索引结构、引擎如何变,而查询需求、查询规则不变。

已经实现的query,有如下特征,不一定合理,仅供参考

偏向基本的:termquery booleanqueryFunctionquery

偏向性能的:MultiTermQuery序列

偏向排序质量的:phrasequery一览

偏向新场景的:spatialquery sqlquery relationquery

image.png


image.png


如何扩展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

QparseFilter sort的扩展,可以理解为FunctionQuery的特例化。

Eg:shape区间交集

将关系映射到平面区间,关系的交集转为平面的交集,从而转义为shape过滤。

Object={ item1item2item3} AND object={item4,item5,item6}

Egsort

结果按照关系维度参数,做类似functionquery的关系模型距离计算。

Egsort

是向量空间模型,输入多个条件,按照向量模型计算得分。

其他高级处理,就是机器学习能自动化相关参数、流程。这一块还没有深入,所以还没有相关经验。


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


目录
相关文章
|
3月前
|
自然语言处理 Java 索引
ElasticSearch 实现分词全文检索 - delete-by-query
ElasticSearch 实现分词全文检索 - delete-by-query
25 1
|
3月前
|
存储 搜索推荐 API
探究:Elasticsearch 文档的 _id 是 Lucene 的 docid 吗?
【8月更文挑战第31天】在深入探索Elasticsearch(简称ES)这一强大的搜索引擎时,了解其底层存储机制——特别是与Lucene的关系,对于优化查询性能、设计高效的数据模型至关重要。其中,一个常见且容易引发误解的问题便是:Elasticsearch中文档的_id字段是否直接等同于Lucene的docid?本文将通过图文并茂的方式,详细剖析这一问题,帮助读者理解两者之间的微妙关系。
83 0
|
Java Apache 索引
10 Lucene索引库查询 - queryparser查询
10 Lucene索引库查询 - queryparser查询
108 0
|
自然语言处理 索引
09 Lucene索引库查询 - query子类查询
09 Lucene索引库查询 - query子类查询
46 0
|
存储 自然语言处理 算法
Elasticsearch Query DSL之全文检索(Full text queries)上篇
Elasticsearch Query DSL之全文检索(Full text queries)上篇
Elasticsearch Query DSL之全文检索(Full text queries)上篇
|
缓存 Java
Elasticsearch Query DSL之Compound queries(复合查询)
Elasticsearch Query DSL之Compound queries(复合查询)
Elasticsearch Query DSL之Compound queries(复合查询)
|
SQL 自然语言处理 Java
Solrflux源码分析-Sql Support within Solr-类Sql的solr搜索实现(2)
假期重新把之前在新浪博客里面的文字梳理了下,搬到这里。
100 0
Solrflux源码分析-Sql Support within Solr-类Sql的solr搜索实现(2)
|
缓存 Java 索引
Solr&Lucene cache简要汇总
假期重新把之前在新浪博客里面的文字梳理了下,搬到这里。本文汇总Solr Lucene cache相关内容。撇开系统结构、架构这些整体性的分析,纯粹从使用方面做梳理。
227 0
Solr&Lucene cache简要汇总
|
自然语言处理 Java 关系型数据库
Elasticsearch Query DSL之全文检索(Full text queries)下篇
Elasticsearch Query DSL之全文检索(Full text queries)下篇
|
算法 前端开发 数据建模
Solr&lucene 默认的spatial search性能总结
假期重新把之前在新浪博客里面的文字梳理了下,搬到这里。介绍地理搜索性能优化的一些经验。
180 0