ElasticSearch语法

适用于ES7.X

一、索引管理

1. 创建索引

PUT /index_name
{
  "settings": { 
    "number_of_shards":2,
    "number_of_replicas":1
  },
  "mappings": {
    "properties": {
      "id":{
        "type": "integer"
      },
      "name":{
        "type": "keyword"
      },
      "age":{
        "type": "long"
      },
      "desc":{
        "type": "text"
      },
      "birthday":{
        "type": "date"
      }
    }
  }
}

settings设置有好多,上面只写了分片和副本数量。

2. 修改索引字段

注:只能新增字段,不能删除字段

POST /index_name/_mapping
{
  "properties": {
      "title":{
        "type": "text"
      }
    }
}

3. 删除索引

DELETE /index_name

4. 查看索引字段类型

GET  /index_name/_mapping

5. 索引数据转移,旧索引数据复制到新索引

POST /_reindex
  {
    "source": {
      "index": "index_name_old"
    },
    "dest": {
      "index": "index_name_new",(提前创建好)
      "version_type": "external"
    }
  }

6. 查看索引列表-健康状态

GET _cat/health

7. 查看索引列表-详细信息

GET _cat/indices?v

8. 查看ik分词情况

GET _analyze
{
  "analyzer": "ik_smart",
  "text": "支付就用支付宝"
}

9. 查看ik分词,最细粒度划分

GET _analyze
{
  "analyzer": "ik_max_word",
  "text": "支付就用支付宝" 
}

二、文档管理

1. 创建文档PUT/POST

区别:put文档必须要指定文档_id;post可指定,可不指定,不指定则会随机生成一个_id

情况1:如果没有提前设定索引中字段类型而直接添加文档,es会对字段数据给自动数据类型,新字段会永久补充进去mapping。

情况2:如果添加的数据字段数量大于提前设定索引中字段数量,可成功,按情况1处理。

情况3:如果添加的数据字段数量小于提前设定索引中字段数量,更可成功。

put指定id

PUT /index_name/_doc/1
{
  "id":1001,
  "name":"张三",
  "age":12,
  "desc":"我的自我描述",
  "birthday":"2020-02-02"
}

post指定id

POST /index_name/_doc/3
{
  "id":1002,
  "name":"张三",
  "age":12,
  "desc":"我的自我描述",
  "birthday":"2020-02-02"
}

post不指定id,自动给_id

POST /index_name/_doc
{
  "id":1003,
  "name":"张三",
  "age":12,
  "desc":"我的自我描述",
  "birthday":"2020-02-02"
}

2. 查询文档

查询所有文档

GET  /index_name/_search

查询指定文档

GET  /index_name/_doc/1

3. 修改文档

全修改:PUT和POST都可以,全部字段均会被修改更新

POST /index_name/_doc/1
{
  "id":1005,
  "name":"张三",
  "age":12,
  "desc":"我的自我描述",
  "birthday":"2020-02-02"
}

部分修改:POST,只修改部分字段数据

POST /index_name/_doc/1/_update
{
  "doc":{
      "name":"李四"
  }
}

4. 删除文档

根据id删除指定文档

DELETE /index_name/_doc/1

5.清空指定索引全部文档

POST index_name/_delete_by_query
{
  "query": {"match_all": {}}
}

根据查询条件清理部分文档

POST index_name/_delete_by_query
{
    "query":{
        "bool":{
            "filter":[
                {
                    "range":{
                        "birthday":{
                            "gte":"2020-06-01 00:00:00",
                            "lt":"2020-07-01 00:00:00"
                        }
                    }
                }
            ]
        }
    }
}

三、复杂查询

语句条件:match匹配查询、bool联合查询、term精确查询

约束条件:must、must_not、should、filter

1. match匹配查询

首先我拿match对desc查询,因为desc是text类型可以进行分词查询;name是keyword不分词,不支持分词查询。

实测,下面的查询结果会查询到desc中包含"%张%" 或 "%三%" 或 "%李%"的文档。

注:张三不是一个词,会被分词器给分开,哇。。。。这样岂不是能查很多,确实,尽量少用match查询text,不够精准。

GET /index_name/_search
{
    "query":{
        "match":{
            "desc":"张三 李"
            }
    }
}

2. bool联合查询,通常搭配must,should,must_not,filter

  1. must、must_not 条件查询,必须满足,类似mysql中and的用法
GET /index_name/_search
{
    "query":{
        "bool":{
            "must":[
                {
                  "match":{
                    "desc":"三 四"
                  }
                },
                {
                  "match": {
                    "age": 12
                  }
                }
            ]
        }
    }
}

  1. should 条件查询,需要满足,并且是或者的关系,类似mysql中or的用
GET /index_name/_search
{
    "query":{
        "bool":{
            "should":[
                {
                  "match":{
                    "desc":"三 四"
                  }
                },
                {
                  "match": {
                    "age": 12
                  }
                }
            ]
        }
    }
}

  1. filter 过滤查询
GET /index_name/_search
{
    "query":{
        "bool":{
            "must":[
                {
                  "match":{
                    "desc":"三 四"
                  }
                }
            ],
            "filter": [
              {
                "range": {
                  "age": {
                    "gte": 10,
                    "lt": 13
                  }
                }
              }
            ]
        }
    }
}

3. term精确查询: 通过倒排索引进行精确查找,用的最多

  • ·match原理是先分析文档,通过分词器进行解析,然后再去文档中查询。
  • ·term直接进行精确查询,term是代表完全匹配,也就是精确查询,搜索前不会再对搜索词进行分词拆解。
  • ·match_phrase短语搜索,要求所有的分词必须同时出现在文档中,同时位置必须紧邻一致。
  1. 简单查询
GET /index_name/_search
{
  "query": {
    "term": {
      "desc":"三" 
    }
  }
}

(2)多条件复合查询

注:term不会分词查询,只是精确查询!!!必须要查满足 “小三” 的文档

GET /index_name/_search
{
    "query":{
        "bool":{
          "must": [
            {
              "term": {
                "desc": "小三"
              }
            },
            {
              "term": {
                "age": 11
              }
            }
          ]
        }
    }
}

terms表示多条件并列,用大括号 [ ] 涵盖所查内容,类似于MySql中in方法

GET /index_name/_search
{
    "query":{
        "bool":{
          "must": [
            {
              "terms": {
                "age": [
                  10,11,12
                ]
              }
            }
          ]
        }
    }
}

或者

GET /index_name/_search
{
    "query":{
        "bool":{
          "must": [
            {
              "terms": {
                "desc": [
                  "我","三"
                ]
              }
            }
          ]
        }
    }
}

多重混合,这个也是用到较多的

GET /index_name/_search
{
    "query":{
        "bool":{
            "must":[
                {
                    "term":{
                        "desc":"三"
                    }
                },
                {
                    "terms":{
                        "age":[
                            10,
                            11,
                            12
                        ]
                    }
                }
            ]
        }
    }
}


must和must_not混合,这里面留意区别下term 和 match条件的不同含义

GET /index_name/_search
{
    "query":{
        "bool":{
            "must":[
                {
                    "term":{
                        "name":"张三"
                    }
                }
            ],
            "must_not":[
                {
                    "term":{
                        "age":"10"
                    }
                },
                {
                    "match":{
                        "desc":"描述"
                    }
                }
            ]
        }
    }
}

尤其注意must和should并列的情况:must和should不可以直接并列,must和must_not可以直接并列

假如,要查姓名叫“张三”,年龄为12岁或者出生日期为2020-02-03的个人信息,一定要注意了。

就好比: name=张三 && age=15 || birthday=2020-02-03这种错误一样,这是不对的。逻辑上似乎说的过去,但在严谨的数学上可不行,并且就算在mysql中也不可以这么写,因为and优先级大于or,会先执行and并列条件,好在mysql中可以将条件括起来,改正为 where name='张三' and (age=12 or birthday='2020-02-03')。

错误的写法: 即便是把age和birthday都放在should里面,elasticsearch也不认。

GET /index_name/_search
{
    "query":{
        "bool":{
            "must":[
                {
                    "match":{
                        "name":"张三"
                    }
                }
            ],
            "should":[
                {
                    "match":{
                        "age":"12"
                    }
                },
                {
                    "match":{
                        "birthday":"2020-02-03"
                    }
                }
            ]
        }
    }
}

正确的逻辑是:(name=张三 && age=15) || (name=张三 &&birthday=2020-02-03),

 正确的写法:先对should分出情况,再给每一种情况进行must约束

GET /index_name/_search
{
    "query":{
        "bool":{
            "should":[
                {
                    "bool":{
                        "must":[
                            {
                                "term":{
                                    "name":"张三"
                                }
                            },
                            {
                                "term":{
                                    "age":12
                                }
                            }
                        ]
                    }
                },
                {
                    "bool":{
                        "must":[
                            {
                                "term":{
                                    "name":"张三"
                                }
                            },
                            {
                                "term":{
                                    "birthday":"2020-02-03"
                                }
                            }
                        ]
                    }
                }
            ]
        }
    }
}

4. 聚合查询collapse和aggs,将重复内容进行折叠(去重)

GET /index_name/_search
{
    "query":{
        "bool":{
            "must":[
                {
                    "term":{
                        "moduleAttr":6424
                    }
                },
                {
                    "terms":{
                        "sortId":[1,72,101]
                    }
                }
            ],
            "filter":[
                {
                    "range":{
                        "pubTime":{
                            "gte":"2020-07-11 09:13:04"
                        }
                    }
                }
            ]
        }
    },
    "sort":[
        {
            "pubTime":{
                "order":"desc"
            }
        }
    ],
    "collapse":{
        "field":"contentId"
    },
    "size":20
}
 
或者
 
GET index_name/_search
{
    "query":{
        "bool":{
            "must":{
                "terms":{
                    "websiteId":[
                        2141391797
                    ]
                }
            },
            "filter":{
                "range":{
                    "pubTime":{
                        "gte":"2020-04-20 00:00:00",
                        "lte":"2020-07-31 23:59:59"
                    }
                }
            }
        }
    },
    "aggs": {
        "my_name(自定义名字)": {
            "terms": {
                "field": "contentId" 
            }
        }
},
    "size":10
}

4.1.初始测试数据

学习SQL中常用的案例,老师信息表

字段信息:name(姓名) | age(年龄) | job(工作岗位) | sex(性别1-男,2-女) | salary(薪资)

#老师信息

PUT /teacher_info/_bulk
{ "index" : {  "_id" : "101" } }
{ "name" : "Tom","age":32,"job":"Math","sex":1,"salary": 3000 }
{ "index" : {  "_id" : "102" } }
{ "name" : "Zhangsan","age":22,"job":"Java","sex":1,"salary": 5000}
{ "index" : {  "_id" : "103" } }
{ "name" : "lisi","age":29,"job":"sports","sex":1,"salary": 4000 }
{ "index" : {  "_id" : "104" } }
{ "name" : "wangwu","age":25,"job":"sports","sex":1,"salary": 4300}
{ "index" : {  "_id" : "105" } }
{ "name" : "Mary","age":30,"job":"H5","sex":2,"salary": 4800}
{ "index" : {  "_id" : "106" } }
{ "name" : "Luccy","age":33,"job":"English","sex":2,"salary": 5500 }
{ "index" : {  "_id" : "107" } }
{ "name" : "Xiaomei","age":23,"job":"English","sex":2,"salary": 5800 }
{ "index" : {  "_id" : "108" } }
{ "name" : "Xiaogao","age":27,"job":"Php","sex":1,"salary": 3900}
{ "index" : {  "_id" : "109" } }
{ "name" : "Dabai","age":26,"job":"Chinese","sex":1,"salary": 4000 }
{ "index" : {  "_id" : "110" } }
{ "name" : "Xiaowei","age":25,"job":"C++","sex":1,"salary": 4500 }

4.2.ES聚合分析查询的写法

在查询请求体中以aggregations节点语法如下:**

"aggregations" : {
    "<aggregation_name>" : {                                 <!--聚合的名字 -->
        "<aggregation_type>" : {                             <!--聚合的类型 -->
            <aggregation_body>                               <!--聚合体:对哪些字段进行聚合 -->
        }
        [,"meta" : {  [<meta_data_body>] } ]?                <!--元 -->
        [,"aggregations" : { [<sub_aggregation>]+ } ]?       <!--在聚合里面在定义子聚合 -->
    }
}

注:aggregations 也可简写为 aggs

4.3.求和(Sum)

案例:求所有老师的薪资总和

注:“size”: 0 ,参数表示不用返回文档列表,只返回汇总的数据即可

GET teacher_info/_search
{
  "size": 0,
  "aggs": {
    "sum_salary": {
      "sum": {
        "field":"salary"
      }
    }
  }
}

4.4.最大值(Max)

示例:求薪资最大值

GET teacher_info/_search
{
  "size": 0,
  "aggs": {
    "max_salary": {
      "max": {
        "field":"salary"
      }
    }
  }
}

4.5.最小值(Min)

案例:求薪资最低值

GET teacher_info/_search
{
  "size": 0,
  "aggs": {
    "min_salary": {
      "min": {
        "field":"salary"
      }
    }
  }
}

4.6.平均值(Avg)

案例:求薪资平均值

GET teacher_info/_search
{
  "size": 0,
  "aggs": {
    "avg_salary": {
      "avg": {
        "field":"salary"
      }
    }
  }
}


4.7.去重数值(cardinality)

类似mysql的 count distinct

案例:老师一共教了多少学科

GET teacher_info/_search
{
    "size": 0,
    "aggs" : {
        "job_count" : {
            "cardinality" : {
                "field" : "job.keyword"
            }
        }
    }
}

由于在创建索引的时候,没有先创建Mapping, job这个字段默认是 text类型,而聚合统计不知道text类型,所以这里需要使用“job.keyword”

字符串类型的参数,在没有指定mapping的情况下,默认生成的类型如上图。

4.8.多值查询-最大最小和平均值

案例:查询最低、最高和平均工资

GET teacher_info/_search
{
  "size": 0,
  "aggs": {
    "max_salary": {
      "max": {
        "field": "salary"
      }
    },
    "min_salary": {
      "min": {
        "field": "salary"
      }
    },
    "avg_salary": {
      "avg": {
        "field": "salary"
      }
    }
  }
}

4.9.返回多个聚合值(Status)

stats 统计,请求后会直接显示多种聚合结果,总记录数,最大值,最小值,平均值,汇总值

GET employees_info/_search
{
  "size": 0,
  "aggs": {
    "salary_stats": {
      "stats": {
        "field":"salary"
      }
    }
  }
}

4.10.百分比(Percentiles)

对指定字段的值按从小到大累计每个值对应的文档数的占比,返回指定占比比例对应的值。**

GET teacher_info/_search
{
  "size": 0,
  "aggs": {
    "age_percentiles": {
      "percentiles": {
        "field": "age"
      }
    }
  }
}

默认按照[ 1, 5, 25, 50, 75, 95, 99 ]来统计

返回结果可以理解为:占比为25%的文档的age值 <= 25,或反过来:age<=25的文档数占总命中文档数的25%

因为是默认返回的 ,[ 1, 5, 25, 50, 75, 95, 99 ] 所以 可能存在重复值

key-value形式返回

添加参数"keyed": false

4.11.文档值占比(Percentile Ranks)

这里指定值,查占比。注意占比是小于文档值的比例

GET teacher_info/_search
{
    "size": 0,
    "aggs" : {
        "age_percentiles" : {
            "percentile_ranks" : {
                "field" : "age", 
                "values" : [ 22, 25, 33]
            }
        }
    }
}

下图含义

小于age<=22的占比 5%

小于age<=25的占比 30%

小于age<=33的占比 100%

4.12.中位数查询

案例:求工资中位数

POST teacher_info/_search
{
    "size": 0,
    "aggs": {
        "load_time_outlier": {
            "percentiles": {
                "field": "salary",
                "percents" : [ 50, 99],
                "keyed": false
            }
        }
    }
}

4.13.分组取Top N 之(Top Hits)

案例1:根据性别分组。展示工资排名top3

GET /teacher_info/_search?size=0
{
    "aggs": {
        "top_tags": {
            "terms": {
                "field": "sex"
            },
            "aggs": {
                "top_sales_hits": {
                    "top_hits": {
                        "sort": [
                            {
                                "salary": {
                                    "order": "desc"
                                }
                            }
                        ],
                        "_source": {
                            "includes": [ "name", "sex","salary" ]
                        },
                        "size" : 3
                    }
                }
            }
        }
    }
}

4.14.分组之聚合

案例:根据性别分组求平均工资

GET /teacher_info/_search
{
  "size":0,
  "aggs": {
    "top_tags": {
      "terms": {
        "field": "sex"
      },
      "aggs": {
        "avg_salary": {
          "avg": {
            "field": "salary"
          }
        }
      }
    }
  }
}

4.15.总记录数查询

类似mysql的count

#方式1:统计年龄 >=25 的记录数

GET teacher_info/_count
{
  "query": {
    "range": {
      "age":{
        "gte": 25
      }
    }
  }
}

#方式2:统计年龄 >=25 的记录数

GET teacher_info/_search?size=0
{
  "query": {
    "range": {
      "age":{
        "gte": 25
      }
    }
  }
}

5. 高亮查询

默认高亮格式查询

GET /index_name/_search
{
    "query":{
        "match":{
            "desc":"自我描述"
        }
    },
    "highlight": {
      "fields": {
        "desc": {}
      }
    }
}

自定义高亮代码

GET /index_name/_search
{
    "query":{
        "match":{
            "desc":"自我描述"
        }
    },
    "highlight": {
      "pre_tags": "<p style='color:red'>" ,
      "post_tags": "</p>", 
      "fields": {
        "desc": {}
      }
    }
}

6. 最后说几个常用查询筛选条件:

从上到下,分别是只显示需要返回的字段、查询条件、排序规则、分页从0页开始size为2

GET /index_name/_search
{
    "_source":{
        "includes":[
            "name",
            "age",
            "desc"
        ]
    },
    "query":{
        "match":{
            "name":"张三"
        }
    },
    "sort":[
        {
            "age":{
                "order":"desc"
            }
        }
    ],
    "from": 0,
    "size": 2
}

四、复杂条件修改/删除

1. 条件修改_update_by_query

将desc中含有“三”的数据,desc修改为“张3新的自我介绍”。

POST /index_name/_update_by_query
{
    "script":{
        "source":"ctx._source['desc']='张3新的自我介绍'"
    },
    "query":{
        "bool":{
            "must":[
                {
                    "term":{
                        "desc":"三"
                    }
                }
            ]
        }
    }
}

2. 条件删除_delete_by_query

将desc中含有“3”的数据删除

POST /index_name/_delete_by_query
{
    "query":{
        "bool":{
            "must":[
                {
                    "term":{
                        "desc":"3"
                    }
                }
            ]
        }
    }
}

3.清空索引数据

POST /index_name/_delete_by_query
{
  "query": {"match_all": {}}
}

六、Elasticsearch Painless Script

官网解释,自Elasticsearch 5.x 引入Painless,使得Elasticsearch拥有了安全、可靠、高性能脚本的解决方案。

简单来说就是支持通过Painless脚本语言的方式,对es进行查询、修改、删除等操作,为es提供了更强大的一种操作方式。

doc只可以在_search中访问到。如果是修改操作,使用的是ctx。

https://blog.csdn.net/u013613428/article/details/78134170#%E6%89%B9%E9%87%8F%E6%9B%B4%E6%96%B0

  1. 条件修改
POST /index_name/_update_by_query
{
    "script":{
      "lang":"painless",
      "source":"ctx._source.title=params.newTitile",
      "params":{
          "newTitile":"修改为新的titile"
      }
    },
    "query":{
        "bool":{
            "filter":[
                {
                    "range":{
                        "crawlTime":{
                            "gte":"2020-09-01 00:00:00",
                            "lt":"2020-09-03 00:00:00"
                        }
                    }
                }
            ]
        }
    }
}

或者修改title,在titile后面加一句“加一个后缀”

POST /index_name/_update_by_query
{
    "script":{
      "lang":"painless",
      "source":"ctx._source.title= ctx._source.title+'加一个后缀'"
    },
    "query":{
        "bool":{
            "filter":[
                {
                    "range":{
                        "crawlTime":{
                            "gte":"2020-09-01 00:00:00",
                            "lt":"2020-09-03 00:00:00"
                        }
                    }
                }
            ]
        }
    }
}

参考:Elasticsearch7.x DSL语法之聚合查询 - 灰信网(软件开发博客聚合)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值