elasticsearch源码分析之search模块(server端)

继续接着上一篇的来说啊,当client端将search的请求发送到某一个node之后,剩下的事情就是server端来处理了,具体包括哪些步骤呢?

过程

一、首先我们来看看接收地方其实就是在org.elasticsearch.action.search.TransportSearchAction中,收到请求之后会判断请求的index的shard是否只有一个,如果是一个的话,那么会强制将请求的type设置为QUERY_AND_FETCH,因为所以的事情在此shard上就能够做完了。所以如果设置了routing,而让请求落在了一个shard上时,搜索的效率会高很多的原因。

二、根据不同的type来确定不同的处理方式,这里补充一下,上一篇可能忘记说了,search的type一般来说分为“DFS_QUERY_THEN_FETCH、QUERY_THEN_FETCH、DFS_QUERY_AND_FETCH、QUERY_AND_FETCH”这四种,还有“SCAN、COUNT”在ES2.X里面其实已经被舍弃掉了。我们一般都是用的默认的QUERY_THEN_FETCH,上面说的一个shard的除外。所以本篇就只讨论这种情况了。

三、得到搜索的index所涉及的shard,并依次执行: 1、获取该shard所在的node并执行sendExecuteFirstPhase,实际上是向node发送了一个“QUERY”的请求:

transportService.sendRequest(node, QUERY_ACTION_NAME, request, new ActionListenerResponseHandler<QuerySearchResultProvider>(listener) {
@Override
public QuerySearchResult newInstance() {
return new QuerySearchResult();
}
});

2、node接收到"QUERY"的请求之后,执行executeQueryPhase首先是创建一个search的context,

SearchContext context = new DefaultSearchContext(idGenerator.incrementAndGet(), request, shardTarget, engineSearcher, indexService, indexShard, scriptService, pageCacheRecycler, bigArrays, threadPool.estimatedTimeInMillisCounter(), parseFieldMatcher, defaultSearchTimeout);

创建的具体过程就不详细说了,之后做的事情还是有parseSource、对size做判断(2.X里面最大不超过10000,可以通过配置文件配置)、……

最重要的其实是loadOrExecuteQueryPhase(request, context, queryPhase);,具体的内容是首先从cache里面执行query,如果cache里面没有找到,才会执行queryPhase:queryPhase.execute(context);;里面的处理逻辑就比较复杂了,但是最重要的是searcher.search(query, collector);,其实是调用了Lucene里面IndexSeartcher的search方法。

3、如此一来,第一阶段的query已经做完了,,接下来便是fetch的执行,入口在onFirstPhaseResult这里,在底层同样是向node发送一个“FETCH”请求咯:

4、node接收到“fetch”请求之后,执行executeFetchPhase:

fetch的核心代码如下:

。。。

大意就是轮流通过之前query结果中的docid,然后创建出InternalSearchHit的集合,并将之放在fetchResult中context.fetchResult().hits(new InternalSearchHits(hits, context.queryResult().topDocs().totalHits, context.queryResult().topDocs().getMaxScore()));,并将之返回到发送fetch的node。

四、到目前为止,该获取的数据都已经拿到了,现在要做的则是要把个node的返回结果做merge,merge的操作由SearchPhaseController来控制:

final InternalSearchResponse internalResponse = searchPhaseController.merge(sortedShardList, firstResults,
fetchResults, request);

具体的过程就不细说了,大体就是该排序的就做排序,有aggs的就做aggs……

五、通过listener将上面的结果返回:listener.onResponse(new SearchResponse(internalResponse, scrollId, expectedSuccessfulOps, successfulOps.get(), buildTookInMillis(), buildShardFailures()));给发出接收search请求的node,也就是上一篇说道的client。

总结

这样知道了,为什么返回的结果长那么个鬼样子了。整个过程的话算是走马观花地走了一遍了,其实里面还有很多detail的东西没用讲到,看一张图就知道了:

包括他们分别的具体实现什么的,所以一个查询牵扯到的东西实在太多,等有时间再去深究,可都是财富。

转载请注明出处:http://www.opscoder.info/es_search_server.html

elasticsearch源码分析之search模块(server端)的更多相关文章

  1. elasticsearch源码分析之search模块(client端)

    elasticsearch源码分析之search模块(client端) 注意,我这里所说的都是通过rest api来做的搜索,所以对于接收到请求的节点,我姑且将之称之为client端,其主要的功能我们 ...

  2. Elasticsearch源码分析 - 源码构建

    原文地址:https://mp.weixin.qq.com/s?__biz=MzU2Njg5Nzk0NQ==&mid=2247483694&idx=1&sn=bd03afe5a ...

  3. ADB 源码分析(一) ——ADB模块简述【转】

    ADB源码分析(一)——ADB模块简述 1.Adb 源码路径(system/core/adb). 2.要想很快的了解一个模块的基本情况,最直接的就是查看该模块的Android.mk文件,下面就来看看a ...

  4. 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入

    使用react全家桶制作博客后台管理系统   前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...

  5. Elasticsearch源码分析—线程池(十一) ——就是从队列里处理请求

    Elasticsearch源码分析—线程池(十一) 转自:https://www.felayman.com/articles/2017/11/10/1510291570687.html 线程池 每个节 ...

  6. 【转】Spark源码分析之-deploy模块

    原文地址:http://jerryshao.me/architecture/2013/04/30/Spark%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%E4%B9%8B- ...

  7. (一) Mybatis源码分析-解析器模块

    Mybatis源码分析-解析器模块 原创-转载请说明出处 1. 解析器模块的作用 对XPath进行封装,为mybatis-config.xml配置文件以及映射文件提供支持 为处理动态 SQL 语句中的 ...

  8. Spark源码分析之-Storage模块

    原文链接:http://jerryshao.me/architecture/2013/10/08/spark-storage-module-analysis/ Background 前段时间琐事颇多, ...

  9. DRF框架(一)——restful接口规范、基于规范下使用原生django接口查询和增加、原生Django CBV请求生命周期源码分析、drf请求生命周期源码分析、请求模块request、渲染模块render

    DRF框架    全称:django-rest framework 知识点 1.接口:什么是接口.restful接口规范 2.CBV生命周期源码 - 基于restful规范下的CBV接口 3.请求组件 ...

随机推荐

  1. JVM概论

    引子 Java虚拟机是Java应用程序的执行环境.通常而言,JVM是由一组严格的指令集和一个复杂的内存模型来具体实现的虚拟机,它用来解释编译好的java字节码文件,将字节码转换为特定机器可以执行的本机 ...

  2. 百度地图api的简单应用

    百度地图api 获取经纬度(通过浏览器的) //获取经纬度 window.navigator.geolocation.getCurrentPosition(function(position) { a ...

  3. 【Oracle】RAC控制文件多路复用

    1.—关闭数据库,各个节点都要关闭: [oracle@rac1 ~]$ srvctl stop database -d racdb -o immediate 2.—启动任一节点到nomount状态: ...

  4. DataFrame与数据库的相互转化

    在Spark中,Dataframe简直可以称为内存中的文本文件. 就像在电脑上直接操作txt. csv. json文件一样简单. val sparkConf = new SparkConf().set ...

  5. Cocos2d-x-3.6学习笔记第一天

    系统环境: win7,python2.7 开发工具:vs2013 cocos版本:cocos2d-x-3.6 暂无模拟手机的环境 新建我的第一个cocos2d项目 1.打开cmd,cd到cocos2d ...

  6. mysql Seconds_Behind_Master

    通过show slave status查看到的Seconds_Behind_Master,从字面上来看,他是slave落后master的秒数,一般情况下,也确实这样,通过Seconds_Behind_ ...

  7. Spring cloud服务的提供者建立

    1.0我们要在这里要建立一个服务的提供者模块,是一个module,类似于服务的公共模块 第一步:添加架包 <project xmlns="http://maven.apache.org ...

  8. JS 公鸡2文一只、母鸡1文一只、小鸡0.5文一只若一共有100文钱买100只鸡有多少种方法

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  9. 普通平衡树 Splay

    Code: #include<cstdio> #include<algorithm> #include<cstring> using namespace std; ...

  10. Linux下挂载分区 (本人实例)

    设置分区开机自动挂载 要在/etc/fstab里设置一行 把上面空格去掉就行了