ElasticSearch搜索功能介绍

271 阅读5分钟

简介

搜索查询是对Elasticsearch数据流或索引中有关数据的信息的请求。 你可以将查询视为问题,以Elasticsearch理解的方式编写。  根据你的数据,你可以使用查询来得到以下问题的答案,比如:

  • 服务器上的哪些进程响应时间超过500毫秒? 

  • 我的网络上有哪些用户在上周运行了regsvr32.exe ? 

  • 我网站上的哪些页面包含特定的单词或短语?

  • 一个搜索由一个或多个查询组成,这些查询被组合并发送到Elasticsearch。与搜索查询相匹配的文档 

  • 一个搜索还可能包含用于更好地处理查询的附加信息。例如,搜索可能局限于特定的索引或只返回特定数量的结果。 本文主要介绍es支持哪些搜索的功能,具体如何使用,没有详细说明。

运行一个搜索

你可以使用搜索API来搜索和聚合存储在Elasticsearch数据流或索引中的数据。 API的查询请求体参数接受用query DSL编写的查询。 下面的请求使用匹配查询搜索my-index-000001。该查询将文档与用户相匹配。kimchy的Id值。

GET /my-index-000001/_search
{
  "query": {
    "match": {
      "user.id": "kimchy"
    }
  }
}

在搜索中定义运行时字段

我们可以定义仅作为搜索查询的一部分存在的运行时字段,而不是为数据建立索引然后进行搜索。类似于mysql的别名

在搜索请求中指定一个runtime_mappings部分来定义运行时字段,该字段可以选择包含一个Painless脚本。 例如,下面的查询定义了一个名为day_of_week的运行时字段。所包含的脚本基于@timestamp字段的值计算星期几,并使用emit返回计算值。 该查询还包括一个对day_of_week操作的术语聚合。

GET /my-index-000001/_search
{
  "runtime_mappings": {
    "day_of_week": {
      "type": "keyword",
      "script": {
        "source":
        """emit(doc['@timestamp'].value.dayOfWeekEnum
        .getDisplayName(TextStyle.FULL, Locale.ROOT))"""
      }
    }
  },
  "aggs": {
    "day_of_week": {
      "terms": {
        "field": "day_of_week"
      }
    }
  }
}

上面的聚合的含义是:第一个day_of_week是别名,后面的terms含义是获取包含day_of_week字段的数据 这是一个比较复杂是使用, 知识点的详细说明

响应包含基于day_of_week运行时字段的聚合。在buckets下面是一个值为Sunday的key。查询根据在day_of_week运行时字段中定义的脚本动态计算该值,而不需要为该字段建立索引

{
  ...
  ***
  "aggregations" : {
    "day_of_week" : {
       
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "Sunday",
          "doc_count" : 5
        }
      ]
    }
  }
}

常见的搜索操作

我们可以使用以下选项自定义搜索

Query DSL

Query DSL 查询支持各种查询操作,可以用匹配、过滤、术语、全文检索、地图查询等 

  • 布尔查询和其他复合查询,它允许您组合查询并基于多个条件匹配结果 
  • 术语(term)查询,用于过滤和查找精确匹配的术语级查询 
  • 全文查询,通常在搜索引擎中使用 
  • 地理和空间查询

聚合查询

聚合搜索来获得搜索结果的统计数据和其他分析。 聚合帮助您回答以下问题: 

  • 我的服务器的平均响应时间是多少? 
  • 在我的网络中,用户访问最多的IP地址是什么? 
  • 客户的总交易收入是多少?

搜索多个数据流和索引

可以使用逗号分隔的值和类似grep的索引模式来搜索同一请求中的多个数据流和索引。 你甚至可以从特定的索引提升搜索结果官方文档

分页查询

可以设置分页查询参数,文档说明

选择返回的字段

如果搜索响应命中了。返回的子单包含每个命中的完整文档_source字段。 

  • _source说明: _source字段包含在建立索引时传递的原始JSON文档主体,即定义索引时的所有字段。 如果只需要返回某些字段或者排除某些字段都可以通过查询是用_source参数指定

排序

默认情况下,搜索命中按_score排序,这是一个相关性评分,衡量每个文档与查询的匹配程度。 

  • 要自定义这些分数的计算,请使用script_score查询。
  • 要按其他字段值对搜索命中排序,可以通过sort参数指定排序规则

异步搜索

es支持异步搜索,如果查询时间过长可以选择异步搜索

搜索超时

在搜索时可以设置异步搜索,使用timeout参数 要为所有搜索请求设置集群范围内的默认超时时间,使用集群设置API配置search.default_search_timeout。 如果在请求中没有传递timeout参数, 则使用此全局超时持续时间。 如果全局搜索超时在搜索请求完成之前过期,则使用“取消任务功能”取消该请求。 search.default_search_timeout设置默认为-1(没有超时)。

GET /my-index-000001/_search
{
  "timeout": "2s",
  "query": {
    "match": {
      "user.id": "kimchy"
    }
  }
}

关闭连接

在搜索超时后建议关闭连接,es提供任务管理来处理关闭HTTP连接

跟踪总命中数

通常,如果不访问所有匹配项,就无法准确计算总命中计数,这对于匹配大量文档的查询来说代价很高。因此es在查询方面做了优化 使用track_total_hits参数控制跟踪总命中数。 

  • track_total_hits参数设置为true,则命中数是精准的。返回精准命中数 
  • track_total_hits参数设置为false,则命中是未知的。不返回命中数 
  • track_total_hits设置为数字,则是否准确需要参考relation参数,relation=eq表示total.value值准确, relation=gte则表示总数超过返回的total.value值
GET my-index-000001/_search
{
  "track_total_hits": 100,
  "query": {
    "match": {
      "user.id": "elkbee"
    }
  }
}
------------------------------------------------------------
{
  "_shards": ...
  "timed_out": false,
  "took": 30,
  "hits": {
    "max_score": 1.0,
    "total": {
      "value": 42,         
      "relation": "eq"     
    },
    "hits": ...
  }
}

快速检查匹配的文档

如果只想知道是否有任何文档匹配特定的查询,可以将size设置为0,以表示我们对搜索结果不感兴趣。 比如聚合查询的时候,只关心聚合的结果,可以将size参数设置为0,则只会返回聚合结果,不会返回文档信息 可以将terminate_after设置为1,表示只要找到第一个匹配文档(每个分片),就可以终止查询执行。