Elasticsearch 常用Api
mapping映射属性
mapping
用于约束es中索引库中的文档,定义文档中的字段如何存储和索引的过程。
字段参数配置
是否创建索引
表示字段是否需要用于搜索。index:是否创建索引,默认为true。
分词器
analyzer:使用哪个分词器。
1 | { |
字段数据类型
type:字段数据类型。每一个类型都可以作为数组使用。
字符串
type | 描述 |
---|---|
text | 可分词的文本 |
keyword | 精确值,不可分词,例如:品牌、链接、国家、ip地址等,存储和查询时效率较高 |
数值
type | 描述 |
---|---|
long | 带符号的 64 位整数,最小值为 -2⁶³ ,最大值为 2⁶³-1 。 |
integer | 带符号的 32 位整数,最小值为 -2³¹ ,最大值为 2³¹-1 。 |
short | 带符号的 16 位整数,最小值为 -32,768 ,最大值为 32,767 。 |
byte | 带符号的 8 位整数,最小值为 -128 ,最大值为 127 。 |
double | 双精度 64 位 IEEE 754 浮点数,限制为有限值。 |
float | 单精度 32 位 IEEE 754 浮点数,限制为有限值。 |
half_float | 半精度 16 位 IEEE 754 浮点数,限制为有限值。 |
scaled_float | 一个浮点数,由一个固定的 double 比例因子缩放的 long 支持。通过比例因子将浮点数转换为整数存储,节省磁盘空间,适合精度要求不高的场景。 |
unsigned_long | 无符号 64 位整数,最小值为 0,最大值为 2⁶⁴-1。 |
布尔
boolean:true / false。
日期
type | 描述 |
---|---|
date | 支持指定日期格式类型,例如常用的 yyyy-MM-dd HH:mm:ss 、yyyy-MM-dd 等。默认的日期格式为: `strict_date_optional_time |
date_nanos | 对 date 数据类型的补充。date_nanos 数据类型以纳秒分辨率存储日期,这限制了其日期范围大约从 1970 年到 2262 年,因为日期仍然存储为自纪元以来的纳秒数的长整型。对纳秒的查询在内部会转换为对此长整型表示的范围查询,聚合和存储字段的结果会根据与该字段关联的日期格式转换回字符串。 |
使用
||
作为分隔符来让日期同时支持多种格式,会轮流尝试每一种格式,直到与之相匹配,第一种格式会被用来把毫秒值转换回字符串。
1
2
3
4
5
6
7
8
9
10 {
"mappings": {
"properties": {
"my_date": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
}
}
JSON没有专门的日期(date)类型, 在ES中date类型可以表现为:
字符串格式的日期, 比如:
2015-01-01
,2015/01/01 12:10:30
long类型的自 epoch (1970-1-1) 以来的毫秒数
integer类型的自 epoch (1970-1-1) 以来的秒数(时间戳,timestamp)
在ES内部,日期被转换为UTC格式(如果指定了时区),并存储为long类型的自 epoch (1970-1-1) 以来的毫秒数。date总是被显示为字符串格式,即使他们在JSON文档中是long类型。
binary
二进制类型,值以Base64编码字符串的形式存储。_source
默认不会存储该类型的值,也不可搜索;如果需要实际的存储,请设置 store
属性为true,默认是false。
- store:是否应存储字段值并可从
_source
字段单独检索。- doc_values:是否应以列式方式将字段存储在磁盘上,以便后续用于排序、聚合或脚本。
1 | { |
IP
ip类型的字段只能存储ipv4或ipv6地址。
Array
ES没有独立的数组类型,默认任何字段都可以包含一个或多个值,但数组中的值必须是同一种类型,例如:[“hello”,”world”]、[1,2,3]…。数组可以包含null
值,它会被配置的 null_value 替代 或者 直接被忽略。空数组 []
会被视为没有值的字段。
1 | { |
对象
Object 是type的默认值。假设定义name字段为对象类型,不需要显式定义type的属性值。
JSON对象示例:
1 | { |
在ES内部,下方示例的json对象会被作为文档,此文档被索引为简单的键值对扁平列表。
1 | { |
mapping
声明如下:
1 | { |
那如果对象里面嵌套数组呢?比如下面这个示例:
1 | { |
数组类型怎么扁平化?上面的文档会被ES平铺成这样:
1 | { |
如果将查询条件设置成 user.first=张三 and user.last=Lisi
会被查询出来吗?会!
1 | { |
查询结果并不符合预期,可以通过显式声明类型为nested
来解决。
nested
nested
嵌套类型是object
中的一个特例,可以让array
类型的Object array
独立索引和查询。
ES没有内部对象的概念,因此,ES会把具有层次结构的对象平铺成简单的Key-Values
(键和值列表)。
mapping声明定义示例:
1 | { |
token_count
存储字符串值,分析并统计词的个数,实际是integer
类型。
1 | { |
向文档中插入两条数据:
1 | { "name": "John Smith" } |
查询 name
字段中,分词的个数为3的文档:
1 | { |
range
type | 描述 |
---|---|
integer_range |
带符号 32 位整数的范围,最小值为 -231 ,最大值为 231-1 。 |
float_range |
单精度 32 位 IEEE 754 浮点值的范围。 |
long_range |
带符号 64 位整数的范围,最小值为 -263 ,最大值为 263-1 。 |
double_range |
双精度 64 位 IEEE 754 浮点值的范围。 |
date_range |
date 值的范围。日期范围通过 format 映射参数支持各种日期格式。无论使用哪种格式,日期值都会被解析为自 Unix 纪元以来以 UTC 毫秒为单位的无符号 64 位整数。不支持包含 now 日期数学 表达式的值。 |
ip_range |
支持 IPv4 或 IPv6(或混合)地址的 IP 值范围。 |
应用示例:
1 | PUT /my_range |
插入一条数据:expected_attendees
取值范围为10 ~ 20
, 日期time_frame的范围是2025-01-01 23:59:59 ~ 2025-05-05
。
1 | PUT /my_range/_doc/1?refresh |
范围查询
- relation:范围查询支持
within
、contains
、intersects
(默认)。
1 | GET /my_range/_search |
索引库CURD
ES中通过restful请求操作索引库、文档。请求内容用DSL(Domain Specific Language)语句来表示。
查看全部索引
1 | GET _cat/indices?v |
字段 | 描述 |
---|---|
health | 索引的健康状态,这里是 “yellow”。Elasticsearch 索引的健康状态有三种:green(绿色,健康),yellow(黄色,部分健康),red(红色,不健康)。”yellow” 状态表示索引的某些分片处于未分配状态,但主分片是可用的。 |
status | 索引的状态,这里是 “open”。这表示索引处于打开状态,可以进行读取和写入操作。 |
index | 索引的名称,这里是 “nginx-access-log-2023.09.13”。 |
uuid | 索引的唯一标识符。 |
pri | 主分片(primary shard)的数量,这里是 1 个主分片。 |
rep | 副本分片(replica shard)的数量,这里也是 1 个副本分片。 |
docs.count | 索引中文档的总数,这里是 20。 |
docs.deleted | 索引中已删除的文档数量,这里是 0。 |
store.size | 索引的存储大小,这里是 34.1KB。 |
pri.store.size | 主分片的存储大小,这里也是 34.1KB。 |
创建索引库
1 | PUT /<index> |
查询索引库
1 | GET /<index> |
删除索引库
1 | DELETE /<index> |
修改索引库
索引库和mapping一但创建无法修改,支持添加新的字段,语法如下:
1 | PUT /<index>/_mapping |
文档CRUD
新增
如果不指定文档ID,ES会随机生成一个。
1 | POST /<index>/_doc/文档ID |
查询
1 | GET /<index>/_doc/文档ID |
删除
1 | DELETE /<index>/_doc/文档ID |
修改
全量修改,先删除旧文档,再添加新文档。
1 | PUT /<index>/_doc/文档ID |
局部修改,修改指定字段。
1 | PUT /<index>/_doc/文档ID |
DSL查询文档
官方文档链接。ES基于JSON的DSL(Domain Specific Language)来定义查询语法。
查询基本语法结构
_source:用于设置查询结果返回什么字段,类似Select语句后面指定字段。
1 | GET /<index>/_search |
支持一次搜索多个索引,多个索引使用逗号分隔:
1 | GET /<index1>,<index2>/_search |
按前缀匹配索引名:
1 | GET /<index>*/_search |
执行查询语句,返回的JSON结构:
1 |
|
查询子句:
- query:主要用来编写类似SQL的Where语句,支持布尔查询(and/or)、IN、全文搜索、模糊匹配、范围查询(大于小于)。
- aggs:主要用来编写统计分析语句,类似SQL的group by语句
- sort:用来设置排序条件,类似SQL的order by语句
- 分页查询:主要通过from和size参数设置,类似MYSQL 的limit和offset语句
查询全部数据
查询所有数据,从第0条数据开始,一次返回20条数据。
1 | GET /<index>/_search |
bool组合查询
如果需要编写类似SQL的Where语句,组合多个字段的查询条件,可以使用bool语句,类似SQL中的and
(且)、or
(或)。
语法结构:
- must:类似SQL中的and,必须匹配条件。
- must_not:跟must相反,必须不匹配条件。
- should:类似SQL中or,只要匹配其中一个条件即可。
1 | GET /<index>/_search |
综合应用示例
1 | select * from order_v2 where (order_no='2025051112091209991' and (shop_id>=10 and shop_id<=200)) or tag in (1,2) |
等价SQL的DSL的查询方式:
1 | GET /my_index/_search |
单条件查询
通过match实现全文搜索,将内容分词后再搜索;
例1,搜索 message 包含 34
1 | POST /<index>/_search |
例2,搜索 message 包含 34 或者 包含 36
1 | POST /<index>/_search |
例3,搜索 message 包含 34 并且 包含 36
1 | POST /<index>/_search |
例4,搜索 message 包含 34 36 15 22 中超过 50% 以上比例的
1 | POST /<index>/_search |
例5,使用sort对查询数据排序,并按照size返回查询的数量(desc:降序 / asc:升序)
1 | GET /<index>/_search |
多条件查询
and
条件使用 must
,or
条件使用 should
。
例1,搜索Math学科并且发布时间是指定日期的数据。
1 | GET /<index>/_search |
例2,搜索Math学科或者发布时间是指定日期的数据。
1 | { |
例3,多个条件中,至少满足2个以上。搜索包含Math学科、指定发布日期、题型是选择题的。
1 | { |
例4,同时使用包含和不包含的条件。搜索Math学科,但不是选择题。
1 | { |
高亮显示查询结果
pre_tags:自定义标签的前半部分的html标签、属性及样式。默认标签为<em>
post_tags:自定义标签的后半部分样式。默认为:</em>
示例:
数据部分:中国是世界上人口最多的国家
搜索词:中国
1 | GET /<index>/_search |
搜索结果:
1 | { |
聚合查询
聚合查询,类似在SQL中的group by
。
统计分析主要分为分组和组内聚合两个步骤。组内聚合,类似在SQL中 select
编写的avg
、sum
、count
统计函数;
- 对查询的数据首先进行一轮分组,可以设置分组条件,例如:新生入学,把所有的学生按专业分班,这个分班的过程就是对学生进行了分组。
- 组内聚合,就是对组内的数据进行统计,例如:计算总数、求平均值等等,接上面的例子,学生都按专业分班了,那么就可以统计每个班的学生总数, 这个统计每个班学生总数的计算,就是组内聚合计算。
“桶”的概念
满足特定条件的文档的集合,叫做桶。就是一组数据的集合,对数据分组后,得到一组组的数据,就是一个个的桶。
桶等同于组,分桶和分组是一个意思,ES使用桶代表一组相同特征的数据。
桶聚合:指的就是先对数据进行分组,ES支持多种分组条件,例如:支持类似SQL的group by
根据字段分组,当然ES比SQL更强大,支持更多的分组条件,以满足各种统计需求。
“指标”的概念
指标:对文档进行统计计算方式,又叫指标聚合。常用的指标有:SUM
、COUNT
、MAX
等统计函数。
桶内聚合:先对数据进行分组(分桶),然后对每一个桶内的数据进行指标聚合。
查询语法
- aggregations - 代表聚合查询语句,可以简写为
aggs
。 - 代表一个聚合计算的名字,可以随意命名,因为ES支持一次进行多次统计分析查询,后面需要通过这个名字在查询结果中找到我们想要的计算结果。 - 聚合类型,代表我们想要怎么统计数据,主要有两大类聚合类型,桶聚合和指标聚合,这两类聚合又包括多种聚合类型,例如:指标聚合: sum
、avg
, 桶聚合:terms
、Date histogram
等等。- 聚合类型的参数,选择不同的聚合类型,有不同的参数。 - aggregation_name_2 - 代表其他聚合计算的名字,意思就是可以一次进行多种类型的统计。
1 | { |
应用示例
假设存在一个order索引,存储了每一笔汽车销售订单,里面包含了汽车颜色字段color。
现需统计每一种汽车颜色的销量。
在SQL中:
1 | select count(color) from order group by color |
在ES中:
- size:设置size=0的意思就是,仅返回聚合查询结果,不返回普通query查询结果。
- aggs:聚合查询语句的简写。
- popular_colors:给聚合查询取个名字,叫做
popular_colors
。 - terms:聚合类型为terms,桶聚合的一种,类似SQL的group by的作用,根据字段分组,相同字段值的文档分为一组。
- field:terms聚合类型的参数,这里需要设置分组的字段为color,根据color分组。
1 | GET /order/_search |
查询结果:
1 | { |
指标聚合
类似 SQL 的统计函数,指标聚合可以单独使用,也可以跟桶聚合一起使用。常用的统计函数如下:
Value Count
: 类似 SQL的count
函数,主要用于值聚合,统计文档总数。Cardinality
:类似 SQL 的count(DISTINCT 字段)
, 统计不重复的文档总数。Avg
:求平均值Sum
:求和Max
:求最大值Min
:求最小值
应用示例:
1 | GET /my_index/_search?size=0 |
等价于SQL:select count(type) from sales
查询结果:
1 | { |
桶聚合
目的就是数据分组,先将数据按指定的条件分成多个组(桶),然后对每一个组(桶)进行统计。在ES中统一使用桶(bucket)这个术语。
桶聚合的作用跟SQL的group by的作用是一样的,区别是ES支持更加强大的数据分组能力,SQL只能根据字段的唯一值进行分组,分组的数量跟字段的唯一值的数量相等,例如: group by 店铺id, 去掉重复的店铺ID后,有多少个店铺就有多少个分组。
常用的桶聚合方式:
- Terms: 类似SQL的group by,根据字段唯一值分组
- Histogram:根据数值间隔分组,例如: 价格按100间隔分组,0、100、200、300等等
- Date histogram:根据时间间隔分组,例如:按月、按天、按小时分组
- Range:按数值范围分组,例如: 0-150一组,150-200一组,200-500一组。
应用示例:
1 | GET /order/_search?size=0 |
等价于SQL:select shop_id, count(*) from order group by shop_id
查询结果:
1 | { |
多桶排序
默认情况,ES会根据doc_count
文档总数,降序排序。
ES桶聚合支持两种方式排序:
内置排序
_count:按文档数排序。对 terms 、 histogram 、 date_histogram 有效。
_term:按词项的字符串值的字母顺序排序,只在 terms 内使用。
_key:按每个桶的键值数值排序, 仅对 histogram 和 date_histogram 有效。
1 | GET /cars/_search |
按度量指标排序
通常情况下,根据桶聚合分桶后,都会对桶内进行多个维度的指标聚合,所以也可以根据桶内指标聚合的结果进行排序。
1 | GET /cars/_search |
限制返回桶的数量
如果分桶的数量太多,可以通过给桶聚合增加一个size参数限制返回桶的数量。
1 | GET /cars/_search |