[toc]

前言

本文以命令行为主

其本质还是发送http请求去操作数据

1. 基本格式

es是以RESTFul风格来命名API的,其API的基本格式如下:

http://<ip>:<port>/<索引>/<类型>/<文档id>

这里需要注意的是,该格式从es7.0.0开始,移除Type(类型)这个概念,新的基本格式如下:

http://<ip>:<port>/<索引>/_doc/<文档id>

Type(类型)字段那里变为固定值 _doc

es的动作是以http方法来决定的: 常用的http方法: GET/PUT/POST/DELETE

post 主做修改, put主做创建

post也有创建的功能,特别是插入数据生成随机id时

2. 命令

2.1 创建索引

curl -XPUT http://localhost:9200/xkj_test 没有指定mappings,故为非结构化索引,也没有字段

// 结构化索引: 指定了mappings
curl -X PUT 'localhost:9200/accounts' -d '
{
    "mappings": { // mappings 映射
        "man": { // type
            "properties": { // 具体属性
                "name": { // 字段名
                    "type":"text" // 字段类型
                    // ....还有其他可以选,比如拆分规则,权重值
                },
                "country": {
                    "type":"keyword"
                },
                "age": {
                    "type":"integer"
                },
                "date": {
                    "type": "date",
                    "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
                }
            }
        },
//         "worman": {} // 6.x版本只支持一个type
   		}
	}
}'

其核心是里面的json字符串

一张网图

2.2 插入数据

curl -X POST 'localhost:9200/accounts/person/1000' -d ' 
// 这个1000表示id,如果不写es会自动生成一个,如果连索引和类型也没有也会一并创建,如果id已存在则修改
{
  "user": "张三",
  "title": "工程师",
  "desc": "数据库管理"
}' 

格式是 ip:port/索引/类型/id, 参数是各属性的json字符串

2.3 修改数据

post http://localhost:9200/test/_doc/1/_update

{

  "script": {

    "lang": "painless",

    "inline": "ctx._source.age += 30"

  }

}

关键字”script”: 标志以脚本的方式修改文档

“lang”:表示以何种脚本语言进行修改,“painless”表示以es内置的脚本语言进行修改。此外es还支持多种脚本语言,如Python,js等等

“inline”:指定脚本内容 “ctx”代表es上下文,_source 代表文档

根据条件修改信息:

POST my_index/_update_by_query
{
  "script": {
    "source": "ctx._source['ipsub']=0" 
  },
  "query": {
    "bool": {
      "must_not": [
        {
          "exists": {
            "field": "ipsub"
          }
        }
      ]
    }
  }

上面语句是根据是否存在"ipsub"字段,如果不存在,给信息增加字段"ipsub",并且赋值0

2.4 查看

  1. 查看xkj_test索引数据格式
curl -X GET http://localhost:9200/xkj_test/
  1. 查看xkj_test索引下指定id查看
curl -X GET 'localhost:9200/xkj_test/person/1000?pretty=true'
  1. 根据条件查询
curl -X POST 'localhost:9200/accounts/person/_search'  -d '
// 要带上  _search 关键字
{
  "query" : { "match" : [{ "desc" : "软件" },{ "desc" : "软件 工程" }]}
}'

and 查询: match写多个条件

or 查询: 利用空格的分词,达到or的效果(我猜的)

_score :匹配度

_source:文档的字段

来源: https://www.jianshu.com/p/083d99a1db6e

es的查询五花八门,最好的技术书籍就是官网,以后好好看,如果要查数据,借助可视化界面就够用了

https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html

2.5 删除

删除xkj_test索引

delete http://localhost:9200/xkj_test/

删除xkj_test索引下的数据(指定id)

delete http://localhost:9200/xkj_test/_doc/1

根据条件删除xkj_test索引下test1类型的数据

post http://localhost:9200/xkj_test/test1/_delete_by_query
{
  "query": {
    "range": {
      "createDate": {
        "lt": "now-31d"
      }
    }
  }
}

解释: 删除 createDate 字段下31天前的数据

利用_delete_by_query插件去批量删除

https://blog.csdn.net/weixin_44034192/article/details/89372934

2.6 简单排序

按照指定字段排序,(默认按照分数排序)

GET books/_search
{
  "sort": [
    "price": {
      "order": "desc"
    },
     "age": {
      "order": "desc"
    }
  ]
}
// 按照价格降序排,再按年龄排

在 Elasticsearch 中,默认排序是按照相关性的评分(_score)进行降序排序,也可以按照字段的值排序多级排序多值字段排序、基于 geo(地理位置)排序以及自定义脚本排序,除此之外,对于相关性的评分也可以用 rescore 二次、三次打分,它可以限定重新打分的窗口大小(window size),并针对作用范围内的文档修改其得分,从而达到精细化控制结果相关性的目的。

3. 复杂查询

3.1 Query and filter context

查询子句的行为取决于它是用在查询上下文(query context)还是用在过滤器上下文(filter context):

3.1.1 Query context

在查询上下文中的查询子句回答了“这个文档与这个查询子句的匹配程度是怎样的?”问题。除了决定文档是否匹配以外,查询子句还会计算一个“_score”,它表示文档与其他文档的相关程度(分数)。

3.1.2 Filter context

在过滤器上下文中,一个查询子句回答了“这个文档与查询子句匹配吗?”的问题。这个答案是简单的Yes或者No,也不会计算分数。过滤上下文主要用于过滤结构化数据

PS:Query VS Filter

  1. 查询反应的是文档与查询子句的匹配程度,而过滤反应的是文档是否匹配查询子句
  2. 一个是筛选是否满足条件,情况无非两种:是或不是;一个是看满足条件的记录与查询条件的匹配程度
  3. 哪些满足条件,这是过滤;满足条件的这些记录与条件的匹配程度,这是查询
  4. 过滤不会计算评分,查询会计算评分

3.2 全文查询( Full text)

3.1.1 match query

match查询接受文本/数值/日期类型的数据,分析它们,并构造一个查询。

相当于模糊查询

match是一种布尔类型的查询。这意味着它对提供的文本进行分析,并在分析的过程中为提供的文本构造一个布尔查询。operator 选项可以设置为 or 或者 and 以此来控制布尔子句(默认是 or )。例如

curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
    "query": {
        "match" : {
            "skuName" : "空调"
        }
    }
}'

3.1.2 Match Phrase Query

match_phrase 查询与 match类似,但是它是用于精确匹配或单词接近匹配的。例如:

curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
    "query": {
        "match_phrase" : {
            "skuName" : "this is a test"
        }
    }
}'

3.1.3 Multi Match Query

multi_match 相当于 match 的多字段版本, multi_match可以指定多个字段,而match只能针对一个字段

curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
  "query": {
    "multi_match" : {
      "query":    "this is a test", 
      "fields": [ "subject", "skuName" ] 
    }
  }
}
'
fields 里的字段用 * 支持模糊匹配,  写成这种 [ "subject^3", "skuName" ] 表示subject比skuName重要3倍

3.1.4 Query String Query

支持Lucene查询字符串语法,允许指定 AND | OR | NOT ,并且在单个查询字符串中进行多字段查询, 分词后对每个词都查询

curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
    "query": {
        "query_string" : {
            "default_field" : "skuName",
            "query" : "this  that  thus"
        }
    }
}
'
// 在skuName中查询 this , that , thus 三个词 , 其实质解析成: " this OR that OR thus", 你可以替换OR为AND/NOT
// 还可以指定快 例如:  "query" : "(new york city) OR (big apple)"  这样将被拆分成 “new york city” 和 “big apple” 两部分,并且每一部分都被分析器独立分析
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
    "query": {
        "query_string" : {
            "fields" : ["content", "name"],
            "query" : "this AND that"
        }
    }
}
'
// 等价于
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
    "query": {
        "query_string": {
            "query": "(content:this OR name:this) AND (content:that OR name:that)"
        }
    }
}
'

注意,按操作符拆分

query_string的参数包括:

query  实例被解析的查询文本

default_field  如果没有指定前缀字段的话,这是默认的查询字段。(默认查询所有字段)

default_operator  如果没有明确指定操作符的话,那么这是默认的操作符。例如,如果默认操作符是OR的话,那么“my name is jack”将被翻译成“my OR name OR is OR jack”,同理,如果是AND,则被翻译成“my AND name AND is AND jack”

analyzer  用来解析查询字符串的解析器的名字

allow_leading_wildcard  如果设置了,那么 * 或 ? 允许作为第一个字符。默认是true

lenient  如果设置为true,则格式失败将被忽略

3.2 单词级查询(term text)

全文本查询会在执行之前对查询字符串进行分析,而单词级别查询会对存储在反向索引中的精确的term进行操作。

这些查询通常用于结构化的数据,比如:numbers , dates ,enums 等,而不是对全文本字段。

(PS:也就是说,全文本查询之前要先对文本内容进行分词,而单词级别的查询直接在相应字段的反向索引中精确查找,单词级别的查询一般用于数值、日期等类型的字段上)

3.2.1 Term Query

在指定的字段中查找包含指定的精确的term的文档

term查询将在反向索引(或者叫倒排索引)中查找包含特定的精确的term的文档。例如:

curl -X POST "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
  "query": {
    "term" : { "user" : "Kimchy" } 
  }
}
'
// 查询倒排索引(切词后)中user包含"kimchy"字符串的值,

3.2.2 Terms Query

查找包含指定字段中指定的任何确切term的文档

筛选出与所提供的terms中任何一个匹配的文档

curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
    "query": {
        "terms" : { "user" : ["kimchy", "elasticsearch"]}
    }
}
'
// 查询 切词后包含"kimchy"或者 "elasticsearch"文档

3.2.3 Range Query

查找指定字段在指定范围内包含值(日期、数字或字符串)的文档。

下面的例子返回age字段的值在10到20之间的文档:

curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
    "query": {
        "range" : {
            "age" : {
                "gte" : 10,
                "lte" : 20,
                "boost" : 2.0
            }
        }
    }
}
'

range查询可以接受下列参数:

gte  大于或等于

gt   大于

lte   小于或等于

lt   小于

boost  设置boost值,默认是1.0

在日期范围查询的时候,我们可以指定日期格式。例如:(时间格式es会自动转化,用字符串去查时间格式也能行)

curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
    "query": {
        "range" : {
            "born" : {
                "gte": "01/01/2012",
                "lte": "2013",
                "format": "dd/MM/yyyy||yyyy"
            }
        }
    }
}
'
// 这个例子是查询在2012-01-01到2013-12-31之间出生的人
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
    "query": {
        "range" : {
            "timestamp" : {
                "gte": "2015-01-01 00:00:00", 
                "lte": "now", 
                "time_zone": "+01:00"
            }
        }
    }
}
'

3.2.4 Exsit Query

在特定的字段中查找非空值的文档

curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
    "query": {
        "exists" : { "field" : "user" }
    }
}
'

3.2.5 Prefix Query

查找包含带有指定前缀的term的文档

curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{ 
	"query": {
    	"prefix" : { "user" : "ki" }
  }
}
'

3.2.6 Wildcard Query

支持通配符查询,*表示任意字符,?表示任意单个字符

这个查询效率比较慢

curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
    "query": {
        "wildcard" : { "user" : "ki*y" }
    }
}
'

3.2.7 Regexp Query

curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
    "query": {
        "regexp":{
            "name.first": "s.*y"
        }
    }
}
'

prefix 和 wildcard 和 regexp 三者工作方式是一样的 ,需要扫描倒排索引中的词列表才能找到所有匹配的词,然后依次获取每个词相关的文档 ID

性能对比: prefix > wildcard > regexp

wildcard 和 regexp要避免左模糊查询

官网

3.3 聚合查询

Elasticsearch 的聚合(Aggregations)功能十分强大,允许在数据上做复杂的分析统计。Elasticsearch 提供的聚合分析功能主要有指标聚合(metrics aggregations)桶聚合(bucket aggregations)管道聚合(pipeline aggregations) 三大类,

所有的聚合,无论它们是什么类型,都遵从以下的规则。

  • 使用查询中同样的 JSON 请求来定义它们,而且你是使用键 aggregations 或者是 aggs 来进行标记。需要给每个聚合起一个名字,指定它的类型以及和该类型相关的选项。
  • 它们运行在查询的结果之上。和查询不匹配的文档不会计算在内,除非你使用 global 聚集将不匹配的文档囊括其中。
  • 可以进一步过滤查询的结果,而不影响聚集。

以下是聚合的基本结构:

"aggregations" : { <!-- 最外层的聚合键,也可以缩写为 aggs -->
    "<aggregation_name>" : { <!-- 聚合的自定义名字 -->
        "<aggregation_type>" : { <!-- 聚合的类型,指标相关的,如 max、min、avg、sum,桶相关的 terms、filter  -->
            <aggregation_body> <!-- 聚合体:对哪些字段进行聚合,可以取字段的值,也可以是脚本计算的结果 -->
        }
        [,"meta" : {  [<meta_data_body>] } ]? <!--  -->
        [,"aggregations" : { [<sub_aggregation>]+ } ]? <!-- 在聚合里面在定义子聚合 -->
    }
    [,"<aggregation_name_2>" : { ... } ]* <!-- 聚合的自定义名字 2 -->
}
  • 在最上层有一个 aggregations 的键,可以缩写为 aggs
  • 在下面一层,需要为聚合指定一个名字。可以在请求的返回中看到这个名字。在同一个请求中使用多个聚合时,这一点非常有用,它让你可以很容易地理解每组结果的含义。
  • 最后,必须要指定聚合的类型。

关于聚合分析的值来源,可以取字段的值,也可以是脚本计算的结果

但是用脚本计算的结果时,需要注意脚本的性能和安全性;尽管多数聚集类型允许使用脚本,但是脚本使得聚集变得缓慢,因为脚本必须在每篇文档上运行。为了避免脚本的运行,可以在索引阶段进行计算。

此外,脚本也可以被人可能利用进行恶意代码攻击,尽量使用沙盒(sandbox)内的脚本语言。

text类型默认不支持聚合

查询所有球员的平均年龄是多少,并对球员的平均薪水加 188(也可以理解为每名球员加 188 后的平均薪水)。

POST /player/_search?size=0
{
  "aggs": {
    "avg_age": {
      "avg": {
        "field": "age"
      }
    },
    "avg_salary_188": {
      "avg": {
        "script": {
          "source": "doc.salary.value + 188"
        }
      }
    }
  }
}
// 默认情况下,包含聚合的搜索会返回搜索命中和聚合结果, size 表示返回命中的文档数量,设为0表示只返回聚合结果

3.3.1 Metrics aggregations

指标聚合(又称度量聚合)主要从不同文档的分组中提取统计数据,或者,从来自其他聚合的文档桶来提取统计数据。

这些统计数据通常来自数值型字段,如最小或者平均价格。用户可以单独获取每项统计数据,或者也可以使用 stats 聚合来同时获取它们。更高级的统计数据,如平方和或者是标准差,可以通过 extended stats 聚合来获取。

3.3.1.1 Min Aggregation

Min Aggregation 用于最小值统计。例如,统计 sales 索引中价格最低的是哪本书,查询语句如下:

GET /sales/_search?size=0
{
  "aggs" : {
    "min_price" : { 
      "min" : { 
        "field" : "price" 
      } 
    }
  }
}

聚合结果如下:

{
  ...
  "aggregations": {
    "min_price": {
      "value": 18.0
    }
  }
}

3.3.1.2 Max Aggregation

Max Aggregation 用于最大值统计。例如,统计 sales 索引中type是hat的且价格最高的是哪本书,并且计算出对应的价格的 2 倍值,查询语句如下:

GET /sales/_search?size=0
{
    "query" : {
        "constant_score" : {
          "filter" : {
            "match" : { "type" : "hat" }
          }
       }
   },
  "aggs" : {
    "max_price" : { 
      "max" : { 
        "field" : "price" ,
        "missing": 60
      } 
    },
    "max_price_2" : { 
      "max" : { 
        "field" : "price",
        "script": {
          "source": "_value * 2.0"
        } 
      } 
    }
  }
}

指定的 field,在脚本中可以用 _value 取字段的值

如果指定字段没有值,可以通过 missing 指定默认值;若未指定默认值,缺失该字段值的文档将被忽略(计算)

聚合结果如下:

{
  ...
  "aggregations": {
    "max_price": {
      "value": 188.0
    },
    "max_price_2": {
      "value": 376.0
    }
  }
}

3.3.1.3 Avg Aggregation

Avg Aggregation 用于计算平均值。例如,统计 exams 索引中考试的平均分数,

GET /exams/_search?size=0
{
  "aggs" : {
    "avg_grade" : { 
      "avg" : { 
        "field" : "grade"
      } 
    }
  }
}
{
  ...
  "aggregations": {
    "avg_grade": {
      "value": 78.0
    }
  }
}

除了常规的平均值聚合计算外,elasticsearch 还提供了加权平均值的聚合计算, 详情参见 Elasticsearch 指标聚合之 Weighted Avg Aggregation

用加权平均值代替原本值

3.3.1.4 Sum Aggregation

Sum Aggregation 用于计算总和。

GET /exams/_search?size=0
{
  "aggs" : {
    "hat_prices" : { 
      "sum" : { "field" : "price" } 
    }
  }
}
{
  ...
  "aggregations": {
    "hat_prices": {
      "value": 567.0
    }
  }
}

3.3.1.5 Count Aggregation

Count Aggregation 可按字段统计文档数量。例如,统计 books 索引中包含 author 字段的文档数量,查询语句如下:

GET /books/_search?size=0
{
  "aggs" : {
    "doc_count" : { 
      "value_count" : { "field" : "author" } 
    }
  }
}
{
  ...
  "aggregations": {
    "doc_count": {
      "value": 5
    }
  }
}

3.3.1.6 Cardinality Aggregation

Cardinality Aggregation 用于基数统计,其作用是先执行类似 SQL 中的 distinct 操作,去掉集合中的重复项,然后统计排重后的集合长度。

例如,在 books 索引中对 language 字段进行 cardinality 操作可以统计出编程语言的种类数,查询语句如下:

GET /books/_search?size=0
{
  "aggs" : {
    "all_lan" : { 
      "cardinality" : { "field" : "language" } 
    },
    "title_cnt" : { 
      "cardinality" : { "field" : "title.keyword" } 
    }
  }
}

假设 title 字段为文本类型(text),去重时需要指定 keyword,表示把 title 作为整体去重,即不分词统计

{
  ...
  "aggregations": {
    "all_lan": {
      "value": 8
    },
    "title_cnt": {
      "value": 18
    }
  }
}

3.3.1.7 Stats Aggregation

Stats Aggregation 用于基本统计,会一次返回 count、max、min、avg 和 sum 这 5 个指标。例如,在 exams 索引中对 grade 字段进行分数相关的基本统计,查询语句如下:

GET /exams/_search?size=0
{
  "aggs" : {
    "grades_stats" : { 
      "stats" : { "field" : "grade" } 
    }
  }
}

3.3.1.8 Extended Stats Aggregation

Extended Stats Aggregation 用于高级统计,和基本统计功能类似,但是会比基本统计多出以下几个统计结果,sum_of_squares(平方和)、variance(方差)、std_deviation(标准差)、std_deviation_bounds(平均值加/减两个标准差的区间)。在 exams 索引中对 grade 字段进行分数相关的高级统计,查询语句如下:

GET /exams/_search?size=0
{
  "aggs" : {
    "grades_stats" : { 
      "extended_stats" : { "field" : "grade" } 
    }
  }
}

3.3.1.9 Percentiles Aggregation

Percentiles Aggregation 用于百分位统计。百分位数是一个统计学术语,如果将一组数据从大到小排序,并计算相应的累计百分位,某一百分位所对应数据的值就称为这一百分位的百分位数。默认情况下,累计百分位为 [ 1, 5, 25, 50, 75, 95, 99 ],也可以用percents指定范围。以下例子给出了在 latency 索引中对 load_time 字段进行加载时间的百分位统计,查询语句如下:

GET latency/_search
{
  "size": 0,
  "aggs" : {
    "load_time_outlier" : {
      "percentiles" : {
        "field" : "load_time" ,
        "percents":[30,45] //查询第30%和45%的数据
      }
    }
  }
}

需要注意的是,如上的 load_time 字段必须是数字类型

{
  ...
  "aggregations": {
    "load_time_outlier": {
      "values" : {
        "1.0": 5.0,
        "5.0": 25.0,
        "25.0": 165.0,
        "50.0": 445.0,
        "75.0": 725.0,
        "95.0": 945.0,
        "99.0": 985.0
      }
    }
  }
}

第1%位的数据是5

第5%位的数据是25

&mldr;&mldr;

第99%位的数据是99

3.3.1.10 Percentiles Ranks Aggregation

Percentiles Ranks Aggregation 与 Percentiles Aggregation 统计恰恰相反,就是想看当前数值处在什么范围内(百分位), 假如你查一下当前值 500 和 600 所处的百分位,发现是 90.01 和 100,那么说明有 90.01 % 的数值都在 500 以内,100 % 的数值在 600 以内。

GET latency/_search
{
  "size": 0,
    "aggs" : {
      "load_time_ranks" : {
        "percentile_ranks" : {
          "field" : "load_time", 
          "values" : [500, 600]
        }
      }
  }
}

同样 load_time 字段必须是数字类型

{
  ...
  "aggregations": {
    "load_time_ranks": {
      "values" : {
        "500.0": 90.01,
        "600.0": 100.0
      }
    }
  }
}

可以设置 keyed 参数为 true,将对应的 values 作为桶 key 一起返回,默认是 false

GET latency/_search
{
  "size": 0,
  "aggs": {
    "load_time_ranks": {
      "percentile_ranks": {
        "field": "load_time",
        "values": [500, 600],
        "keyed": true
      }
    }
  }
}
{
  ...
  "aggregations": {
    "load_time_ranks": {
      "values": [
        {
          "key": 500.0,
          "value": 90.01
        },
        {
          "key": 600.0,
          "value": 100.0
        }
      ]
    }
  }
}

3.3.2 bucket aggregations

bucket 可以理解为一个桶,它会遍历文档中的内容,凡是符合某一要求的就放入一个桶中,分桶相当于 SQL 中的 group by。从另外一个角度,可以将指标聚合看成单桶聚合,即把所有文档放到一个桶中,而桶聚合是多桶型聚合,它根据相应的条件进行分组。

桶数最多 65536 个,可修改

3.3.2.1 Terms Aggregation

Terms Aggregation 用于词项的分组聚合。最为经典的用例是获取 X 中最频繁(top frequent)的项目,其中 X 是文档中的某个字段,如用户的名称、标签或分类。由于 terms 聚集统计的是每个词条,而不是整个字段值,因此通常需要在一个非分析型的字段上运行这种聚集。原因是, 你期望“big data”作为词组统计,而不是“big”单独统计一次,“data”再单独统计一次。

支持字段类型 Keyword, Numeric, ip, boolean, binary.

用户可以使用 terms 聚集,从分析型字段(如内容)中抽取最为频繁的词条。还可以使用这种信息来生成一个单词云。

{
  "aggs": {
    "profit_terms": {
      "terms": { 
        "field": "skuName"
      }
    }
  }
}

结果:

{
  ...
  "aggregations": {
    "genres": {
      "doc_count_error_upper_bound": 0,   // 错误文档的个数
      "sum_other_doc_count": 0,    // 未统计的文档个数
      "buckets": [                        
        {
          "key": "electronic",
          "doc_count": 6
        },
        {
          "key": "rock",
          "doc_count": 3
        },
        {
          "key": "jazz",
          "doc_count": 2
        }
      ]
    }
  }
}

返回值中,默认按doc_count数量降序排序, 可以用order字段指定排序规则

可以用size字段控制返回的桶数

3.2.2.2 Filter Aggregation

Filter Aggregation 是过滤器聚合,可以把符合过滤器中的条件的文档分到一个桶中,即是单分组聚合。

{
  "aggs": {
    "age_terms": {
      "filter": {"term":{"gender":"F"}},
      "aggs": {
        "avg_age": {
          "avg": {
            "field": "age"
          }
        }
      }
    }
  }
}

在聚合操作中加入过滤,比 过滤后再聚合要差, 上面的效率比下面的效率要差

POST /sales/_search?size=0&filter_path=aggregations
{
  "query": { "term": { "type": "t-shirt" } },
  "aggs": {
    "avg_price": { "avg": { "field": "price" } }
  }
}

3.2.2.3 Filters Aggregation

Filters Aggregation 是多过滤器聚合,可以把符合多个过滤条件的文档分到不同的桶中,即每个分组关联一个过滤条件,并收集所有满足自身过滤条件的文档。

{
  "size": 0,
  "aggs": {
    "messages": {
      "filters": {
        "filters": {
          "errors": { "match": { "body": "error" } },
          "warnings": { "match": { "body": "warning" } }
        }
      }
    }
  }
}

在这个例子里,我们分析日志信息。聚合会创建两个关于日志数据的分组,一个收集包含错误信息的文档,另一个收集包含告警信息的文档。而且每个分组会按月份划分。

filters 写多个过滤器比 写过filter效率好

3.2.2.4 Range Aggregation

Range Aggregation 范围聚合是一个基于多组值来源的聚合,可以让用户定义一系列范围,每个范围代表一个分组。在聚合执行的过程中,从每个文档提取出来的值都会检查每个分组的范围,并且使相关的文档落入分组中。注意,范围聚合的每个范围内包含 from 值但是排除 to 值。

{
  "aggs": {
    "age_range": {
      "range": {
        "field": "age",
          "ranges": [{
            "to": 25
          },
          {
            "from": 25,
            "to": 35
          },
          {
            "from": 35
          }]
        },
        "aggs": {
          "bmax": {
            "max": {
              "field": "balance"
            }
          }
        }
      }
    }
  }
}

3.2.2.5 Date Range Aggr

日期范围聚合是专用于日期值的范围聚合。该聚合和正常的 范围 聚合的区别主要在于:该聚合可以用 日期数学 表达式表示 from 值 和 to 值,还可以指定 返回 from 和 to 响应字段的日期格式。注意,该聚合包含 from 值,但不包含 to 值。(左闭右开的区间)

POST /sales/_search?size=0
{
  "aggs": {
    "range": {
      "date_range": {
        "field": "date",
        "format": "MM-yyyy",
        "ranges": [
          { "to": "now-10M/M" },  
          { "from": "now-10M/M" } 
        ]
      }
    }
  }
}

to: < 现在减去 10 个月,向下舍入到月初

from: >= 现在减去 10 个月,向下舍入到月初

在上面的例子中,我们创建了两个范围桶,第一个桶会将早于 10 个月之前的所有文档存储,第二个桶会将从 10 月之前开始的文档存储。

{
    ...
    "aggregations": {
        "range": {
            "buckets": [
                {
                    "to": 1.4436576E12,
                    "to_as_string": "10-2015",
                    "doc_count": 7,
                    "key": "*-10-2015"
                },
                {
                    "from": 1.4436576E12,
                    "from_as_string": "10-2015",
                    "doc_count": 0,
                    "key": "10-2015-*"
                }
            ]
        }
    }
}

时间格式和java的一样

es-中文文档

3.2.2.6 Range Aggr

基于多桶值源的聚合,使用户能够定义一组范围 - 每个范围代表一个桶。 在聚合过程中,将从每个文档中提取的值根据每个存储区范围进行检查,并将相关/匹配文档“存储”到“存储区”中。 请注意,该聚合包含 from 值,但不包含 to 值

GET /_search
{
  "aggs": {
    "price_ranges": {
      "range": {
        "field": "price",
        "ranges": [
          { "to": 100.0 },
          { "from": 100.0, "to": 200.0 },
          { "from": 200.0 }
        ]
      }
    }
  }
}

结果:

{
  ...
  "aggregations": {
    "price_ranges": {
      "buckets": [
        {
          "key": "*-100.0",
          "to": 100.0,
          "doc_count": 2
        },
        {
          "key": "100.0-200.0",
          "from": 100.0,
          "to": 200.0,
          "doc_count": 2
        },
        {
          "key": "200.0-*",
          "from": 200.0,
          "doc_count": 3
        }
      ]
    }
  }
}

3.4 复合查询

复合查询包装其他复合查询或叶查询,以组合它们的结果和分数,改变它们的行为,或者从查询切换到过滤上下文。

简单的说是 将多种查询条件组合到一起

3.4.1 Bool query

  • filter

    子句在过滤器上下文中执行,这意味着计分被忽略,并且子句被视为用于缓存。(过滤掉不要的数据)

  • must

    子句(查询)必须出现在匹配的文档中,并将有助于得分。(用来做匹配的,表示需要出现在文档里)

  • must_not

    子句(查询)不得出现在匹配的文档中。子句在过滤器上下文中执行,这意味着计分被忽略,并且子句被视为用于缓存。

  • should

    子句(查询)应出现在匹配的文档中。【注意should的最小匹配数】

关于should子句,特别要注意:

如果这个布尔查询位于query context,并且有must或者filter子句,那么即使should子句没有匹配任何文档,也没关系

如果是位于filter context,或者既没有must也没有filter,那么至少有"指定"个should查询必须匹配文档。这个行为可以通过设置minimum_should_match参数来显式地控制。(至少满足几个should子句), 可以是正负整数/正负百分比等各种比例 (默认值是0)

参数详情

image

GET product/_search
{
  "query": {
    "bool": {
     "filter": [
       {
         "range": {
           "sellPrice": {
             "gte": 1
           }
         }
       }
     ],
     "must": [
       {
         "match": {
           "skuName": "空调"
         }
       }
     ]
    }
  }
 , "_source": "skuName"
}
// 查询skuName中"空调"的文档,并且过滤出sellPrice大于等于1的文档

filter 子句类可包含 bool query,实现更复杂的逻辑, (俄罗斯套娃之深圳分套)

// 多个条件
GET service-java-logs-2021.07.16/_search
{
  "_source": "message", 
  "query": {
    "bool": {
      "must": [
        {
          "match_phrase": {
            "message": "ERROR"
          }
        }
      ],
      "must_not": [
        {
          "wildcard": {
            "message": "*navigation*"
          }
        },
        {
          "match": {
            "message": "defaultParameterMap"
          }
        },
        {
          "match": {
            "message": "parameters"
          }
        }
      ], 
      "filter": [
        {
          "term": {
            "log.file.path.keyword": "/opt/online-shop-manage/logs/online-shop-manage-provider.log"
          }
        }
      ]
    }
  }
}

3.4.2 boosting query

来源:

https://www.cnblogs.com/hong-fithing/p/11221020.html

http://www.ruanyifeng.com/blog/2017/08/elasticsearch.html

https://www.cnblogs.com/hirampeng/p/10035858.html

https://www.cnblogs.com/cjsblog/p/9910788.html

微信es系列

https://www.knowledgedict.com/tutorial/elasticsearch-sort.html