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. BZOJ 4033 树形DP

    http://blog.csdn.net/mirrorgray/article/details/51123741 安利队长blog- 树形dp吧,状态挺显然的,dp[x][j]表示以x为根的子树中,选 ...

  2. A - Antipalindrome

    Problem description A string is a palindrome if it reads the same from the left to the right and fro ...

  3. WPF全球化与本地化

    当一个App需要推出多语言版本时,就需要使用到[全球化与本地化]服务. 原理及过程 资源文件中包含了所有的控件信息,通过导出这些控件信息,修改其对应的相关属性(比如TextBlock的Text属性)的 ...

  4. Java 系列之spring学习--依赖注入(二)

    一.依赖注入的三种方式 接口注入,set注入,构造函数注入 二.构造函数注入 2.1.测试类 package test; public class test01 { public String msg ...

  5. Codeforces Round #448

    Pizza Serparation #include<stdio.h> #include<string.h> #include<stdlib.h> #include ...

  6. javascript中变量命名冲突的问题

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. 命令模式 Command design pattern in C++

    参考https://sourcemaking.com/design_patterns/command/cpp/2 Create a class that encapsulates some numbe ...

  8. tomcat_logs

    tomcat logs 目录下各日志文件的含义 参考地址: http://www.cnblogs.com/signheart/p/0ed0bef7dfadf59534eec76ad4607654.ht ...

  9. RabbitMQ学习笔记(4)----RabbitMQ Exchange(交换机)的使用

    1. fanout模式 1.1 Publish/Subscribe(发布/订阅)结构图 上图表示一个消费者消费消息之后,不讲消息直接存储到队列,而是使用两个消费者各自声明一个队列,将各自的对应的队列与 ...

  10. elasticsearch元数据

    _source元数据 put /test_index/test_type/1 { "test_field1": "test field1", "tes ...