Elasticsearch搜索过程详解

前言

说明:本文章使用的ES版本是:6.7.0git

在上一篇文章Elasticsearch如何建立索引?中,介绍了ES写入文档的过程。github

接下来咱们具体的看一下ES中,搜索过程是怎样的算法

在ES中搜索

按照前面几篇文章的步骤,咱们直接开始debug搜索的过程。上一篇文章中咱们写入了以下的数据json

{
    "id":6,
    "title": "我是文件标题,可被搜索到66",
    "text":  "文本内容,ES时如何索引一个文档的66",
    "date":  "2014/01/06"
}'

如今执行以下请求,对ES服务器发起搜索请求:缓存

curl -X GET 'localhost:9200/index_name/type_name/_search?pretty&q=title:66' -H 'Content-Type: application/json'

搜索能够接收下面的形式的请求:服务器

clipboard.png

客户端

  1. 根据路由,RestSearchAction接收并开始处理请求
  2. RestSearchAction解析并验证搜索参数,并将其封装成SearchRequest,并指定服务端要处理该请求的Action:indices:data/read/search

服务端(master节点)

  1. 根据SearchRequest的index构造相应的ShardsIterator(分片迭代器),shardIterators由localShardsIterator(当前节点分片迭代器(默认一个节点上,一个索引有5个分片))和remoteShardIterators(其余节点分片迭代器)合并而成,根据搜索条件,构建搜索策略。而后遍历全部的shard。并发

    • 搜索策略app

      • 最多遍历分片数量LONG最大值2^63-1
      • 若是只有一个分片,搜索类型只能是:QUERY_THEN_FETCH
      • 是否查询缓存
      • 遍历分片的最大并发数Math.min(256, Math.max(节点数, 1)*节点分片数),节点默认分片数:5
  2. 构造异步请求Action,将请求转发到各个节点,等待回调
  3. 遍历全部节点,构造节点查询参数ShardSearchTransportRequest对象,对每一个节点执行查询操做 clipboard.png
  4. 执行查询阶段,首先在cache里面判断是否有缓存,若是有则执行缓存查询;若是cache里面没有,执行QueryPhase类的execute()方法,他调用lucene的searcher.search对索引进行查询,查询成功回调onShardResult方法并返回docIds,查询失败回调onShardFailure(计数失败状况,并尝试在副本分片上进行查询)
  5. 查询阶段会计算文档的相关性得分用于排序: clipboard.png
  6. Fetch阶段:master接收到各个节点返回的docIds后,发起数据Fetch请求,经过docId和其分片ID到对应分片抓取数据,后合并数据返回给客户端

大体的查询时序逻辑:
clipboard.pngcurl

搜索总结

  1. Query阶段能够知道,一个搜索会遍历这个索引下的全部分片,每一个分片都会执行一次搜索,并返回相同数量的文档ID。好比搜索条件要查询5条数据,有5个分片,则最终会查询25条数据,排序后取前面5条数据
  2. 查询和计算权重得分在Lucene完成,聚合是在ES中实现的
  3. 搜索会遍历全部的分片,因此分片的数量影响着搜索的性能,而分片的数量也决定了ES能承载的最大数据量。因此在具体的应用中,须要在两者之间选择平衡
  4. 计算文档权重得分,每搜索一次,都会根据搜索条件从新计算一次,对搜索性能影响很大

系列文章

  1. 搜索引擎ElasticSearch源码编译和Debug环境搭建
  2. 搜索引擎ElasticSearch的启动过程
  3. Elasticsearch建立索引流程
  4. Elasticsearch搜索过程详解
  5. Elasticsearch搜索相关性排序算法详解
  6. Elasticsearch中的倒排索引