type
status
date
slug
summary
tags
category
password

1、Query DSL

Query DSL(Domain Specified Language)是 Elasticsearch 提供的一种基于 JSON 的查询语言,用于构建复杂的搜索查询。Elasticsearch 的检索主要有两种方式:
  1. _search + 请求参数。在 _search 后面拼接请求参数字符串。这种方式缺点是请求参数越来越多,搜索条件越来越复杂的情况下,很难满足需求。
  1. _search + 请求体。下面这个请求实现和上面相同的效果。
这个 JSON 格式的请求体数据就称为 Query DSL。Elasticsearch 把 Lucene 功能的绝大部分封装成基于 JSON 的 Query DSL 查询语法。可以构建复杂的查询条件。Query DSL 是日常最常用的查询方式,是我们的学习重点。一个最简单的 Query DSL 语法如下:
返回结果:
  • took: 表示我们执行整个搜索请求消耗了多少毫秒
  • timed_out: 表示本次查询是否超时这里需要注意当timed_out为True时也会返回结果,这个结果是在请求超时时ES已经获取到的数据,所以返回的这个数据可能不完整。且当你收到timed_out为True之后,虽然这个连接已经关闭,但在后台这个查询并没有结束,而是会继续执行
  • _shards: 显示查询中参与的分片信息,成功多少分片失败多少分片等。
  • hits: 匹配到的文档的信息
    • total:表示匹配到的文档总数
    • max_score:为文档中所有 score 的最大值
    • hits:为查询到的文档结果,默认包含查询结果的前十个文档,每个文档都包含文档的index、type、id、score和source数据。结果文档默认情况下是按照相关度(score)进行降序排列,也就是说最先返回的是相关度最高的文档。
Query DSL 提供了两种主要的检索方式:
  • 全文检索(Full-text queries):针对文本内容的搜索,会对查询字符串进行分析处理,适用于搜索非结构化的文本数据,适用于 text 类型的字段。
  • 词项检索(Term-level queries):针对精确值的搜索,不会对查询文本进行分析处理,适用于精确匹配。

1.1 全文检索

全文查询主要用于 text 类型的字段,在执行查询之前会分析查询字符串进行分词处理。全文检索的特点:
  • 会对查询文本进行分词处理
  • 应用分析器(analyzer)处理文本
  • 计算查询词与文档的相关性得分(_score)
  • 不区分大小写(通常)
  • 适用于 text 类型的字段。

1.1.1 match_all 查询所有

elasticsearch 一般不会返回所有所有数据,默认返回前 10 条数据。可以结合 fromsize 使用分页查询功能,还可以结合 sort 实现排序功能。

1.1.2 match 匹配

match 有两种匹配情况:
  • 基本类型(非字符串)和字符(keyword)类型,精确匹配。
  • 字符串(text)类型,全文检索,首先会针对查询语句进行解析(经过 analyzer),主要是对查询语句进行分词,分词后查询语句的任何一个词项被匹配,文档就会被搜到,默认情况下相当于对分词后词项进行 or 匹配操作,最终会按照评分进行排序返回结果。注意不会进行正则匹配,比如"mcb",只会查找出现"mcb"这个单词单独出现的文档,其他包含"mcb"的单词比如"mcb1"、"mcb2"之类的都不会匹配到。
如果要使用match进行精确匹配,可以使用 字段名.keyword
这种方式和 match_phrase 的区别是
  • 字段名.keyword 是精确匹配,要完全等于 value 值才会返回。
  • match_phrase 是短语匹配,只要包含 value 值就会返回。

1.1.3 match_phrase 匹配短语

match_phrase 首先会把 query 内容分词,分词器可以自定义,同时文档还要满足以下两个条件才会被搜索到:
  • 分词后所有词项都要出现在该字段中(相当于 and 操作)。
  • 字段中的词项顺序要一致。
比如有以下 3 个文档,使用 match_phrase 查询 “what life”,只有前两个文档会被匹配。

1.1.4 multi_match 多字段匹配

用于搜索多个字段。例如下面查询内容为 mill,查询字段为 stateaddress
multi_match 还支持对要搜索的字段的名称使用通配符。

1.2 词项检索

词项检索常用于结构化的数据如数字、日期、枚举类型等,会对倒排索引中存储的词项进行精确匹配操作。词项检索的特点:
  • 不分析查询文本
  • 不计算相关性得分(通常返回的 _score 是固定的)
  • 区分大小写
  • 适用于 keyword、date、数字等类型的字段

1.2.1 term 精确匹配

和 match 一样,匹配某个属性的值。全文检索字段用 match,其他非 text 字段匹配用 term。

1.2.2 terms 精确匹配多个单词

terms 查询是 term 查询的升级,可以用来查询文档中包含多个词的文档。比如,想查询 title 字段中包含关键词 “java” 或 “python” 的文档

1.2.3 range 范围查找

用于匹配在某一范围内的数值型、日期类型或者字符串型字段的文档。使用 range 查询只能查询一个字段,不能作用在多个字段上。range 查询支持的参数有以下几种:
  • gt 大于,查询范围的最小值,也就是下界,但是不包含临界值。
  • gte 大于等于,和 gt 的区别在于包含临界值。
  • lt 小于,查询范围的最大值,也就是上界,但是不包含临界值。
  • lte 小于等于,和 lt 的区别在于包含临界值。
下面查询 15 <= age <= 25 的数据。

1.2.4 exists 非空查询

查询会返回字段中至少有一个非空值的文档。例如
以下文档会匹配上面的查询:
  • { "user" : "jane" } 有 user 字段,且不为空。
  • { "user" : "" } 有 user 字段,值为空字符串。
  • { "user" : "-" } 有 user 字段,值不为空。
  • { "user" : [ "jane" ] } 有 user 字段,值不为空。
  • { "user" : [ "jane", null ] } 有 user 字段,至少一个值不为空即可。
下面的文档都不会被匹配:
  • { "user" : null } 虽然有 user 字段,但是值为空。
  • { "user" : [] } 虽然有 user 字段,但是值为空。
  • { "user" : [null] } 虽然有 user 字段,但是值为空。
  • { "foo" : "bar" } 没有 user 字段。

1.2.5 prefix 前缀查询

prefix 查询用于查询某个字段中以给定前缀开始的文档,比如查询 title 中含有以 java 为前缀的关键词的文档,那么含有 java、javascript、javaee 等所有以 java 开头关键词的文档都会被匹配。查询 description 字段中包含有以 win 为前缀的关键词的文档,查询语句如下:

1.2.6 regexp 正则查询

Elasticsearch 也支持正则表达式查询,通过 regexp query 可以查询指定字段包含与指定正则表达式匹配的文档。可以代表任意字符, “a.c.e” 和 “ab...” 都可以匹配 “abcde”,a{3}b{3}、a{2,3}b{2,4}、a{2,}{2,} 都可以匹配字符串 “aaabbb”。例如需要匹配以 W 开头紧跟着数字的邮政编码,使用正则表达式查询构造查询语句如下:

1.3 复合查询

复合查询就是把一些简单查询组合在一起实现更复杂的查询需求,除此之外,复合查询还可以控制另外一个查询的行为。

1.3.1 bool 组合多条件过滤

最常用的复合查询,bool 查询允许组合多个查询子句,使用 must、should、must_not、filter 选项来表示简单查询之间的逻辑,每个选项都可以出现 0 次到多次,文档是否符合每个“must”或“should”子句中的标准,决定了文档的“相关性得分”。得分越高,文档越符合您的搜索条件。 默认情况下,Elasticsearch 返回根据这些相关性得分排序的文档。它们的含义如下:
  • must:必须匹配所有查询条件,相当于逻辑运算的 AND,且参与文档相关度的评分。
  • should:应该匹配一个或多个查询条件,相当于逻辑运算的 OR,且参与文档相关度的评分。如果匹配了会提高score,不匹配也不影响检索结果。如果query中只有should且只有一种匹配规则,那么should的条件就会被作为默认匹配条件改变查询结果。
  • must not:必须不匹配所有查询条件。需要注意的是,must_not 语句不会影响评分,它的作用只是将不相关的文档排除
  • filter:过滤器,类似于 must。跟 must 的唯一区别是,filter 不计算相关性得分,所有数据返回的 score 都为 0。

1.3.2 boosting 查询

允许降低某些文档的权重而非完全排除:

1.4 嵌套查询

1.4.1 nested 嵌套查询

当一个字段值是对象的时候,通常会被解析为Nested (嵌套)类型。查询对象里面的某个属性的时候,需要使用 nested 查询。例如有两条数据如下:
如果需要根据 users.name 来查询,需要使用 nested 查询。
  • path: 复杂对象的 key。
  • score_mode:(可选)匹配子对象的分数相关性分数。默认 avg,使用所有匹配子对象的平均相关性分数。
  • ignore_unmapped:(可选)是否忽略 path 未映射,不返回任何文档而不是错误。默认为 false,如果 path 不对就报错。

2、聚合查询

Elasticsearch 的聚合(Aggregations)功能允许你对数据进行分组、统计和分析。聚合类似于 SQL 中的 GROUP BY 和聚合函数(如 COUNT、SUM、AVG 等),但功能更加强大和灵活。 聚合查询有三种类型:
  • 桶集合(Bucket aggregations):对查询出的数据进⾏分组 group by,再在组上进⾏指标聚合。桶等同于组,分桶和分组是一个意思,ES使用桶代表一组相同特征的数据。
  • 指标聚合(Metrics aggregations):先对数据进行分组(分桶),然后对每一个桶内的数据进行指标聚合,例如求最⼤、最⼩、和、平均值、去重等指标的聚合。
  • 管道聚合(Pipeline aggregations):对其他聚合的结果进行再聚合,用的比较少。
聚合的语法如下:
  • aggregation_name:聚合名称,这个可以自己任意定义。因为ES支持一次进行多次统计分析查询,后面需要通过这个名字在查询结果中找到我们想要的计算结果。
  • aggregation_type:聚合类型,代表我们想要怎么统计数据,主要有两大类聚合类型:桶聚合和指标聚合,这两类聚合又包括多种聚合类型,例如:指标聚合:sum、avg, 桶聚合:terms、Date histogram等等。
  • meta:元数据,用的比较少。
  • aggregations:子聚合,也就是说聚合里面还可以嵌套聚合。
  • aggregation_name_2:并列聚合名称,同一个 aggregations 下可以并列多个聚合名称,也就是可以一次进行多种类型的统计。
下面是一个简单使用示例,对 age 求平均值。
  • aggs:表示使用聚合统计,聚合要和 query 一起配合使用,才能对返回的数据进行统计。
  • avgAge:聚合名称,用户自定义名称。
  • avg:聚合类型,avg 表示求平均值,还可以使用 max 求最大值,min 求最小值,sum 求合等。
  • field:需要聚合的字段。
  • size:查询结果条数,0 表示不返回查询数据,只返回聚合结果。
聚合里面还可以嵌套聚合,例如按照年龄聚合, 并且请求这些年龄段的这些人的平均薪资

2.1 桶集合

桶聚合,目的就是数据分组,先将数据按指定的条件分成多个组,然后对每一个组进行统计。 组的概念跟桶是等同的,在ES中统一使用桶(bucket)这个术语。 桶聚合的作用跟 SQL 的 group by 的作用是一样的,区别 Elasticsearch 支持更加强大的数据分组能力,SQL 只能根据字段的唯一值进行分组,分组的数量跟字段的唯一值的数量相等,例如: group by 店铺 ID, 去掉重复的店铺 ID 后,有多少个店铺就有多少个分组。 常用的桶聚合如下:
  • Terms 聚合:类似 SQL 的 group by,根据字段唯一值分组
  • Histogram 聚合:根据数值间隔分组,例如: 价格按 100 间隔分组,0、100、200、300等等
  • Date histogram 聚合:根据时间间隔分组,例如:按月、按天、按小时分组
  • Range 聚合:按数值范围分组,例如: 0-150一组,150-200一组,200-500一组。
提示:桶聚合一般不单独使用,都是配合指标聚合一起使用,对数据分组之后肯定要统计桶内数据,在ES中如果没有明确指定指标聚合,默认使用Value Count指标聚合,统计桶内文档总数。

2.1.1 terms 聚合

类似于 mysql 的 group by 功能,都是根据字段唯一值对数据进行分组(分桶),字段值相等的文档都分到同一个桶内。
返回数据

2.1.2 histogram 聚合

histogram(直方图)聚合,主要根据数值间隔分组,使用histogram聚合分桶统计结果,通常用在绘制条形图报表。
返回结果

2.1.3 date histogram 聚合

类似 histogram 聚合,区别是 Date histogram 可以很好的处理时间类型字段,主要用于根据时间、日期分桶的场景。
返回数据

2.1.4 range 聚合

range 聚合,按数值范围分桶。
返回结果
大家仔细观察的话,发现range分桶,默认key的值不太友好,尤其开发的时候,不知道key长什么样子,处理起来比较麻烦,我们可以为每一个分桶指定一个有意义的名字。

2.1.5 多桶嵌套查询

2.1.6 多桶排序

类似terms、histogram、date_histogram这类桶聚合都会动态生成多个桶,如果生成的桶特别多,有时候我们需要确定这些桶的排序顺序,并限制返回桶的数量。 默认情况,ES会根据 doc_count 文档总数,降序排序。ES桶聚合支持两种方式排序:
  • 内置排序
  • 按度量指标排序

2.1.7 内置排序

内置排序参数:
  • _count - 按文档数排序。对 terms 、 histogram 、 date_histogram 有效
  • _term - 按词项的字符串值的字母顺序排序。只在 terms 内使用
  • _key - 按每个桶的键值数值排序, 仅对 histogram 和 date_histogram 有效

2.1.8 按度量排序

通常情况下,我们根据桶聚合分桶后,都会对桶内进行多个维度的指标聚合,所以我们也可以根据桶内指标聚合的结果进行排序。

2.1.9 限制返回桶的数量

如果分桶的数量太多,可以通过给桶聚合增加一个 size 参数限制返回桶的数量。

2.2 指标聚合

2.2.1 value_count 统计数量

value_count表示统计⾮空字段的⽂档数,类似 mysql 的 count 函数。

2.2.2 cardinality 去重统计数量

也是用于统计文档的总数,跟 Value Count 的区别是,cardinality 聚合会去重,类似于 mysql 的 count(DISTINCT 字段)

2.2.3 stats 统计

stats同时统计 count max min avg sum 5个值

2.2.4 extended_stats 扩展统计

extended_stats ⽐ stats 多4个统计结果: 平⽅和、⽅差、标准差、平均值加/减两个标准差的区间。

2.2.5 percentiles 区间统计

percentiles表示占⽐百分位对应的值统计,默认返回[ 1, 5, 25, 50, 75, 95, 99 ]分位上的值
还可以指定百分位区间
Elasticsearch系列:索引管理(Mapping、Setting)Elasticsearch系列:REST API
Loading...