以下操作均为在 kibana 中的测试操作, postman 请手动加上ip和port
#查询索引健康状态
GET /_cat/health?v
#查看每个操作返回结果字段的意义
GET /_cat/health?help
#查看集群中节点信息
GET /_cat/nodes?v
#查看集群中的索引信息
GET /_cat/indices?v
#简化写法
GET /_cat/indices?v&h=health,status,index
#创建索引
PUT /xiaobai
#删除索引
DELETE /xiaobai
#使用这种方式创建mapping,索引名在节点中必须不存在
#创建类型 mapping
PUT /xiaobai/user
{
"mappings": {
"user":{
"properties":{
"name":{"type":"text"},
"age":{"type":"integer"},
"birth":{"type":"date"}
}
}
}
}
# 创建index(xiaobai)后,在指定index中添加类型mapping(user)
POST /xiaobai/user
{
"user": {
"properties": {
"id": { "type": "text" },
"name": { "type": "text" },
"age": { "type": "integer" },
"created": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
}
}
}
}
#查看类型mapping # 语法:GET /索引名/_mapping/类型名
GET /xiaobai/_mapping/user
#新增单个文档 语法: PUT(POST) /索引名/类型名/id
PUT /xiaobai/user/1
{
"name":"张三",
"age":18,
"created":"2018-01-01"
}
#或
POST /xiaobai/user
{ # 在不指定id的情况下 ES默认生成一个不重复的id
"name":"李四",
"age":20,
"created":"2018-01-02"
}
#根据id查询单个
GET /xiaobai/user/rMtpDmgBfCGt9hTRaYyW
GET /xiaobai/user/1
#修改单个 这样做是直接替换 而不是动态修改(只修改指定的field)
PUT /xiaobai/user/q8toDmgBfCGt9hTROIxL
{
"doc":{
"name":"李大侠",
"age":21
}
}
#实现动态修改
POST /xiaobai/user/rMtpDmgBfCGt9hTRaYyW/_update
{
"doc": {
"name":"李小侠1"
}
}
#删除单个
DELETE /xiaobai/user/1
DELETE /xiaobai/user/q8toDmgBfCGt9hTROIxL
#批量添加
POST /xiaobai/user/_bulk
{"index":{}}
{"name":"王五","age":21,"created":"2018-01-03"}
{"index":{}}
{"name":"赵六","age":22,"created":"2018-01-04"}
GET /xiaobai/user/rstvDmgBfCGt9hTR14ws
#批量操作(删除+修改)
POST /xiaobai/user/_bulk
{"update":{"_id":"rstvDmgBfCGt9hTR14ws"}}
{"doc":{"name":"啦啦啦"}}
{"delete":{"_id":"1"}}
探索之前的准备:
创建zpark索引
PUT /xiaobai
{
"mappings": {
"user":{
"properties":{
"name":{"type":"text"},
"realname":{"type":"text"},
"age":{"type":"integer"},
"birthday":{"type":"date"},
"salary":{"type":"double"},
"address":{"type":"text"}
}
}
}
}
批量插入测试数据
POST /xiaobai/user/_bulk
{"index":{"_id":1}}
{"name":"zs","realname":"张三","age":18,"birthday":"2018-12-07","salary":1000.0,"address":"北京市昌平区沙阳路55号"}
{"index":{"_id":2}}
{"name":"ls","realname":"李四","age":20,"birthday":"2017-10-10","salary":5000.0,"address":"北京市朝阳区三里屯街道21号"}
{"index":{"_id":3}}
{"name":"ww","realname":"王五","age":25,"birthday":"2016-03-15","salary":4300.0,"address":"北京市海淀区中关村大街新中关商城2楼511室"}
{"index":{"_id":4}}
{"name":"zl","realname":"赵六","age":20,"birthday":"2003-04-20","salary":12300.0,"address":"北京市海淀区中关村软件园9号楼211室"}
{"index":{"_id":5}}
{"name":"tq","realname":"田七","age":35,"birthday":"2001-08-11","salary":1403.0,"address":"北京市海淀区西二旗地铁辉煌国际大厦负一楼"}
搜索有两种方式:一种是通过 URL 参数进行搜索,另一种是通过 DSL(Request Body) 进行搜索
DSL:Domain Specified Language,特定领域语言
使用请求体可以让你的JSON数据以一种更加可读和更加富有展现力的方式发送。
### URL实现
#### q=* 查询所有字段
#### sort=age:desc 根据age字段降序(desc)排序
GET /xiaobai/user/_search?q=*&sort=age:desc&pretty
### DSL实现
#### "match_all":{} 查询所有
#### "age":"desc" 年龄降序
GET /xiaobai/user/_search
{
"query":{
"match_all":{}
},
"sort":{
"age":"desc"
}
}
### URL实现
#### from=2&size=2 从第二条开始查询两条数据
GET /xiaobai/user/_search?q=*&sort=_id:asc&from=2&size=2
### DSL实现
#### "from":2, 从第2条开始 检索
#### "size":2 查出2条
GET /xiaobai/user/_search
{
"query":{
"match_all":{}
},
"sort":{
"_id":"asc"
},
"from":1,
"size":3
}
### 需求: 查询 address 在海淀区的所有用户,并高亮
### DSL实现
GET /xiaobai/user/_search
{
"query": {
"match": {
"address":"海淀区"
}
},
"highlight": {
"fields": {
"address": {}
}
}
}
###需求 : 查询 name 是 zs 关键字的用户
### URL实现
GET /xiaobai/user/_search?q=name:zs
### DSL实现
GET /xiaobai/user/_search
{
"query":{
"term": {
"name": {
"value": "zs"
}
}
}
}
###需求 : 查询年龄在 20~30 岁之间的用户
### DSL实现
GET /xiaobai/user/_search
{
"query": {
"range": {
"age": {
"gte": 20,
"lte": 30
}
}
}
}
### 需求:查询真实姓名以 李 开头的用户
### DSL实现
GET /xiaobai/user/_search
{
"query": {
"prefix": {
"realname": {
"value": "李"
}
}
}
}
### 需求:查询名字以 s 结尾的用户
### URL实现
GET /xiaobai/user/_search?q=name:*s 查询名字以 s 结尾的用户
GET /xiaobai/user/_search?q=name:z* 查询名字以 z 开头的用户
###DSL实现
GET /xiaobai/user/_search
{
"query": {
"wildcard": {
"name": {
"value": "*s"
}
}
}
}
### 需求: 查询 id 为1,2,3的用户
### DSL实现
GET /xiaobai/user/_search
{
"query": {
"ids": {
"values": [1,2,3]
}
}
}
###需求:模糊查询 realname 中包含 张 关键字的用户
### DSL实现
GET /xiaobai/user/_search
{
"query": {
"fuzzy": {
"realname": {"value": "张"}
}
}
}
must :查询结果必须符合该查询条件(列表)。
should :类似于or的查询条件。
must_not :查询结果必须不符合查询条件(列表)。
### 需求:查询 age 在15-30岁之间并且 name 必须通配z*
### DSL实现
GET /xiaobai/user/_search
{
"query": {
"bool": {
"must": [
{
"range": {
"age": {
"gte": 15,
"lte": 30
}
}
},
{
"wildcard": {
"name": {
"value": "z*"
}
}
}
],
"must_not": [
{
"regexp": {
"name": ".*s"
}
}
]
}
}
}
其实准确来说,ES中的查询操作分为2种:查询(query)和过滤(filter)。查询即是之前提到的query查询,它(查询)默认会计算每个返回文档的得分,然后根据得分排序。而**过滤(filter)**只会筛选出符合的文档,并不计算得分,且它可以缓存文档。所以,单从性能考虑,过滤比查询更快。
换句话说,过滤适合在大范围筛选数据,而查询则适合精确匹配数据。一般应用时,应先使用过滤操作过滤数据,然后使用查询匹配数据。
GET /xiaobai/user/_search
{
"query":{
"bool": {
"must": [
{"match_all": {}}
],
"filter": { # 过滤年龄大于等于25岁的用户
"range": {
"age": {
"gte": 25
}
}
}
}
}
}
term、terms的含义与查询时一致。term用于精确匹配、terms用于多词条匹配
GET /xiaobai/user/_search
{
"query":{
"bool": {
"must": [
{"match_all": {}}
],
"filter": {
"terms": {
"name": ["zs","ls"]
}
}
}
}
}
见示例
exists 过滤指定字段没有值的文档
GET /xiaobai/user/_search
{
"query": {
"bool": {
"must": [
{
"match_all": {}
}
],
"filter": {
#
排除salary为null的结果
"exists": {
"field": "salary"
}
}
}
},
"sort": [
{"_id": {"order": "asc"}}
]
}
==========所有薪水为空的数据====
GET /xiaobai/user/_search
{
"query": {
"bool": {
"must_not": [
{
"exists": {
"field": "salary"
}
}
]
}
}
}
需要过滤出若干指定_id的文档,可使用标识符过滤器(ids)
GET /xiaobai/user/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"address": "昌平区"
}
}
],
"filter": {
"ids": { # id 过滤器
"values": [1,2,3]
}
}
}
}
}
聚合提供了功能可以分组并统计你的数据。理解聚合最简单的方式就是可以把它粗略的看做SQL的GROUP BY操作和SQL的聚合函数。
ES中常用的聚合:
metric(度量)聚合:度量类型聚合主要针对的number类型的数据,需要ES做比较多的计算工作
bucketing(桶)聚合:划分不同的“桶”,将数据分配到不同的“桶”里。非常类似sql中的group语句的含义
ES中的聚合API(格式)如下:
"aggregations" : { // 表示聚合操作,可以使用aggs替代
"" : { // 聚合名,可以是任意的字符串。用做响应的key,便于快速取得正确的响应数据。
"" : { // 聚合类别,就是各种类型的聚合,如min等
<aggregation_body> // 聚合体,不同的聚合有不同的body
}
[,"aggregations" : { [<sub_aggregation>]+ } ]? // 嵌套的子聚合,可以有0或多个
}
[,"" : { ... } ]* // 另外的聚合,可以有0或多个
}
# Avg Aggregation 平均值查询,作用于number类型字段上。如:查询用户的平均年龄
POST /xiaobai/user/_search
{
"aggs":{
"age-avg":{
"avg":{
"field":"age"
}
}
}
}
## 可以先进行过滤查询,在进行平均值聚合
POST /xiaobai/user/_search
{
"query":{
"ids":{
"values":[1,2,3]
}
},
"aggs":{
"age-avg":{ # 给查询结果命名 随意
"avg":{
"field":"age"
}
}
}
}
# Max Aggregation 最大值查询。如:查询员工的最高工资
POST/xiaobai/user/_search
{
"aggs":{
"salary-max":{ # 给查询结果命名 随意
"max":{
"field":"salary"
}
}
}
}
# Min Aggregation 最小值查询。如:查询员工的最低工资
POST/xiaobai/user/_search
{
"aggs":{
"salary-min":{ # 给查询结果命名 随意
"min":{
"field":"salary"
}
}
}
}
# Sum Aggregation 相加之和的查询。如:查询员工工资之和
POST/xiaobai/user/_search
{
"aggs":{
"salary-sum":{ # 给查询结果命名 随意
"sum":{
"field":"salary"
}
}
}
}
# Stats Aggregation 统计查询,一次性统计出某个字段上的常用统计值
POST/xiaobai/user/_search
{
"aggs":{
"age-stats":{
"stats":{
"field":"age"
}
}
}
}
# Range Aggregation 自定义区间范围的聚合 我们可以自己手动地划分区间,ES会根据划分出来的区间将数据分配不同的区间上去。
# 如: 统计0-20岁,20-35岁,35~60岁用户人数
POST /xiaobai/user/_search
{
"aggs":{
"age-range":{
"range":{
"field":"age",
"ranges":[
{
"from":0,
"to":20
},{
"from":20,
"to":35
},{
"from":35,
"to":60
}
]
}
}
}
}
# Terms Aggregation 自定义分组依据Term,对分组后的数据进行统计
# 如:根据年龄分组,统计相同年龄的用户
POST /xiaobai/user/_search
{
"aggs":{
"age-terms":{
"terms":{
"field":"age", # 这里的域的类型不能为text,否则报错
"size":3 # 查询三条
}
}
}
}
# 时间区间聚合专门针对date类型的字段,它与Range Aggregation的主要区别是其可以使用时间运算表达式。
# now+10y:表示从现在开始的第10年。
# now+10M:表示从现在开始的第10个月。
# 1990-01-10||+20y:表示从1990-01-01开始后的第20年,即2010-01-01。
# now/y:表示在年位上做舍入运算。
#如: 统计生日在2019年、2018年、2017年的用户
POST /xiaobai/user/_search
{
"aggs":{
"birthday-dra":{
"date_range":{
"field":"birthday",
"format":"yyyy-mm-dd",
"ranges":[
{
"from":"now/y", #今年(2019)的1月1日
"to":"now" #当前的时间 从今年元旦至今
},{
"from":"now/y-1y", # 去年(2018)的1月1日
"to":"now/y" # 当年的1月1日 去年元旦到今年元旦
},{
"from":"now/y-1y", # 前年(2017)的1月1日
"to":"now/y" # 去年的1月1日 去年元旦到今年元旦
}
]
}
}
}
}
# Histogram Aggregation
# 直方图聚合,它将某个number类型字段等分成n份,统计落在每一个区间内的记录数。它与前面介绍的Range聚合
# 非常像,只不过Range可以任意划分区间,而Histogram做等间距划分。既然是等间距划分,那么参数里面必然有距
# 离参数,就是interval参数。
#根据年龄间隔(5岁)统计
POST /xiaobai/user/_search
{
"aggs":{
"age-his":{
"histogram":{
"field":"age",
"interval":5 # 间隔5
}
}
}
}
# 日期直方图聚合,专门对时间类型的字段做直方图聚合。这种需求是比较常用见得的,我们在统计时,通常就会按
# 照固定的时间断(1个月或1年等)来做统计。
# 如:按年统计用户
POST /xiaobai/user/_search
{
"aggs":{
"birthday-dha":{
"date_histogram":{
"field":"birthday",
"interval":"year",
"format":"yyyy-mm-dd"
}
}
}
}
# 聚合操作是可以嵌套使用的。通过嵌套,可以使得metric类型的聚合操作作用在每一bucket上。我们可以使用ES的嵌套聚合操作来完成稍微复杂一点的统计功能。
# 如:统计每年中用户的最高工资
POST /xiaobai/user/_search
{
"aggs":{
"birthday-dha":{
"date_histogram":{
"field":"birthday",
"interval":"year",
"format":"yyyy-mm-dd"
}
},"max-salary":{
"max":{
"field":"salary"
}
}
}
}