转载--solr的searching过程(1)

2019-03-27 00:22|来源: 网路

1.拦截请求,解析请求并构建相应的handler

发送检索请求,例如:http://localhost:8983/solr3.5/core2/select/?q=*%3A*&version=2.2&start=0&rows=10&indent=on

首先他将被SolrDispatchFilter拦截。

?

doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

通过对request的分析,获知当前request是做什么的(/select),并构造相应的handlerSearchHandler)。

 

2.SolrCore出面处理上层工作(具体工作交由handler处理)

handlerSolrQueryRequestSolrQueryResponse交由solrCoreexecute方法处理

?

public void execute(SolrRequestHandler handler, SolrQueryRequest req, SolrQueryResponse rsp)

在该方法中主要还是由handler来完成的。

SolrRequestHandler是一个接口,他主要的方法就是:

?

public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp);

SolrRequestHandler的实现类的结构图如下:

其中RequestHandlerBase为大部分的Handler实现了部分功能,主要包括

?

public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp){

  ......

  handleRequestBody( req, rsp );

  ......

}

然而具体怎么做就交给具体的子类去执行了!(handleRequestBody( req, rsp );

例如:这里是做检索,那么就交由SearchHandler处理。

(这里的设计方式有点类似于servletGenericSerlet实现了一些公用方法,而具体的则有其子类完成,例如HttpServlet

 

3.SearchHandler具体的检索过程

现在的检索没有使用shards,在跟踪代码的过程中,发现以下过程是检索的主要环节。

?

if(!rb.isDebug()) {

        // Process

        for( SearchComponent c : components ) {

         <strong> c.process(rb);</strong>

        }

      }

从中可知真正的检索需要经过多个SearchComponent,在当前的实验环境下包括6个,如下:

 

4.各个SearchComponent配合工作完成检索

我们先重点了解QueryComponent

获得SolrIndexSearcher,这个对象是检索的主要执行者。

同时获取SolrIndexSearcher.QueryCommandSolrIndexSearcher.QueryResult,并将其作为查询条件和查询结果提交给SolrIndexSearcher进行检索。

?

searcher.search(result,cmd);

SolrIndexSearchersearch方法如下:

?

public QueryResult search(QueryResult qr, QueryCommand cmd) throws IOException {

    <strong>getDocListC(qr,cmd);</strong>

    return qr;

  }

getDocListC又是一个比较复杂的方法,在这里加入的cache

如果当前检索被缓存了(缓存也是个重点内容,后续详细分析!),那么直接返回结果,否则重新进行检索,检索的方法是:

?

private void getDocListNC(QueryResult qr,QueryCommand cmd)

在该方法中,和我们使用lucene进行检索十分相似,采用的具体方法是:

?

super.search(query, luceneFilter, collector);

检索完成将结果进行封装,放入QueryResult当中。

?

qr.setDocList(new DocSlice(0,sliceLen,ids,scores,totalHits,maxScore));

检索完成后,将结果放入缓存中,造福后人

至此QueryComponent的工作就算完成了。

如果做简单查询(如:http://localhost:8983/solr3.5/core2/select/?q=*%3A*&version=2.2&start=0&rows=10&indent=on

那么后面5Component就直接过了(没有真正被执行)。

 

5.收尾工作

将结果封装好,写入相应的ResponseHeaders,关闭SolrQueryRequestsolrCore

 

-----------------------------------------------------

以上是solr-searching最粗略的过程,本着先脉络后细节的思想,以后再对各个重要环节做深入分析。

searching主要执行方法如下:

SolrDispatchFilterdoFilter,execute

->SolrCore(execute)

->RequestHandlerBase(handleRequest)

->SearchHandler(handleRequestBody) //有可能执行多个Component

->QueryComponent(process)

->SolrIndexSearcher(search,getDocListC)

 


转自:http://yinyayun.blog.51cto.com/3095228/1100279

相关问答

更多
  • 完成您所寻找的最佳方法是将回复的内容(以及您希望进行搜索的任何其他字段)非规范化为其父消息。 这在太阳黑子中非常简单。 您可能在网上进行研究的另一种常见情况是根据评论内容搜索博客帖子。 这里需要注意一点:由于非规范化,您需要一个after_save挂钩,以便在添加或更新时回复可以重新索引其父级。 在你的情况下,变化可能看起来像这样... class Message < ActiveRecord::Base # … after_save :reindex_parent searchab ...
  • 因此,从solr 7.3开始,对默认字段的支持已被删除。 请参阅https://lucene.apache.org/solr/guide/7_3/major-changes-in-solr-7.html?hl=defaultSearchField#other-deprecations-and-removals 现在,当您在搜索时未指定字段时,没有要搜索的默认字段。 唯一的方法是使用df运算符。 因此,在您的情况下,如果您希望如果未指定该字段,那么您需要在类别字段中搜索,然后使用以下查询: q = https ...
  • 尝试使用olr.WordDelimiterFilterFactory 测试用例:
    您需要将字段复制到默认搜索字段(在本例中为文本),或者使用要搜索的字段限定查询: .../select?q=city:Nashua&wt=xml&indent=true 要阅读的内容: 默认搜索字段 复制字段 两者都记录在这里: https://wiki.apache.org/solr/SchemaXml You need to either copy your fields into the default search field (in this case text) or qualify your ...
  • 问题是,字段fr_Name是string类型,这意味着它没有被分析或标记,如果你想搜索一些包含空格的东西,比如Apple Mac Book Pro ,那么你需要使用双引号来完成匹配。 因此,查询"fq":"fr_Name":\"Apple Mac Book Pro\"应该适合您。 来自Solr wiki的一些参考资料: 字符串(UTF-8编码的字符串或Unicode)。 字符串用于小型字段,不以任何方式进行标记或分析。 他们有一个小于32K的硬限制。 Add this fieldtype
  • repo.findByUsernameContainsOrNameContains("someUsername", "someName"); 将产生q=username:*someUsername* OR name:*someName* 一旦用空字符串repo.findByUsernameContainsOrNameContains("", "someName"); 这将转换为q=username:** OR name:*someName* 所以username:**将匹配所有拥有用户名的文件。 repo. ...
  • 尝试这个 http://localhost:8887/solr/souro_core2/select?q=name:souro&indent=true&shards=shard1,shard2 这应该工作如果你有收藏名称souro_core2有两个分片。 Finally i got my answer. In both shards there was an "id" field and both were containing value 1. But after doing bit research ...
  • 您可以使用url http://host:port/solr/dataimport?command=status或甚至不使用任何命令来轮询dataimporthandler的状态,因为status是默认值。 通过这种方式,您可以获得有关dataimport进程的一些详细信息,您可以查看它是否仍在进行中。 看看可用的命令 。 You can poll the status of the dataimporthandler with the url http://host:port/solr/dataimpor ...
  • 使用Solr,您可以使用保存差异的文档来维护字段。 差异可以在总+ 1和-1之间。 Solr允许您使用函数查询来增强字段值。 因此,您可以使用差异字段上的提升进行查询,其中文档的差异得分优于其他字段。 从索引前端开始,由于这种差异会经常发生变化,因此每次都需要更新相应的文档。 Solr不允许更新单个字段,因此您需要处理差异字段的增量更新。 如果您担心这一点,可以尝试使用ExternalFileField 。 这允许在单独的文件中将某些文档字段(例如排名,索引外部的流行度)映射到索引。 可以更新文件并提交索引 ...
  • 根据Solr快速入门 搜索 可以通过REST客户端,cURL,wget,Chrome POSTMAN等以及可用于许多编程语言的本机客户端查询Solr。 Solr Admin UI包含一个查询构建器界面 - 请参阅http:// localhost:8983 / solr /#/ gettingstarted / query中的gettingstarted query选项卡。 因此,您应该能够使用HTTP请求采样器执行搜索 将您的Solr核心名称和YOUR_QUERY_HERE为您的实际查询。 您还可以使用X ...