• ElasticSearch学习(四):的增删改查、高亮、聚合、别名、重建索引


    目录

    1、Restfull

    2、查看ES的基本信息

    2.1、查看集群信息

    3、索引操作

    3.1、创建并显示指定索引字段的类型

    3.2、通过创建文档的方式自动映射字段的类型

    4、文档操作:

    4.1、增加文档信息

    4.2、更新文档信息

    4.3、获取文档信息

    4.4、删除文档信息

    5、批量操作 

    5.1、批量查询

    5.2、批量插入数据

    5.3、批量删除:

    5.4、批量更新

    6、查询数据

    6.1、查询所有文档信息

    6.2、根据关键字查询文档信息

    6.3、全文匹配查询(match)

     6.3.1、单字段匹配查询

     6.3.2、多字段匹配查询:

    6.4、顺序匹配(Match_phrase)

    6.5、多字段查询(multi_match)

    6.6、精确匹配(term)

    6.7、多词条精确匹配(terms) 

    6.8、指定匹配数组内容(Terms_set)

    6.9、多条件复合查询

    6.10、查询子句

    6.11、SQL 查询

    6.12、Range 范围查询与 Sort 排序

    6.13、通配符查询(Wildcard)

    6.14、指定Id值查询(Ids)

    6.15、以特定前缀开头(Prefix)

    6.16、多查询一次提交(Msearch)

    6.17、查询字段是否存在(Exists)

    6.18、控制输出的的字段

    6.18.1、通过 filter_path 来控制输出的的字段 

     6.18.2、通过 _source来控制输出字段

    6.18.3、通过 _source 中的 includes 属性来控制输出字段

     6.18.4、通过 _source 中的 exclude属性排除指定字段输出(exclude后续版本已弃用)

    6.18.5、设置 _source 为 false,这样不返回任何的 _source 信息:

     6.19、分页查询

    6.20、高亮查询

    7、Profile 调试工具

    8、聚合查询

    8.1、指标聚合分析(Metric )

    8.1.1、avg示例:查询所有用户的平均年龄

    8.1.2、avg示例:查询地址在 “广东省”用户的平均工资

    8.1.3、max示例:查询年龄的最大值

    8.1.4、min示例:查询年龄的最小值

    8.1.5、sum示例:查询符合条件的年龄之和

    8.1.6、cardinality示例:查询所有用户不同年龄的数量

    8.1.7、stats示例:查出所有用户的年龄stats信息

    8.1.8、extended_stats示例:查出所有用户的年龄extended_stats信息

    8.1.9、percentile示例:查出所有用户的年龄占比

    8.2、Bucket 分桶聚合分析

    8.2.1、分桶group by示例:根据年龄聚合查询

    8.2.2、分桶group by示例:根据年龄段聚合查询

    8.2.3、分桶group by示例:根据用户出生日期的年月分组分段聚合查询

    8.2.4、group by 进阶示例:按照年龄聚合,并查询出每个年龄这些人的平均薪资

    8.2.5、group by 进阶示例:查出所有年龄分布,并且这些年龄段中 性别为男 的平均薪资和 性别为女 的平均薪资以及这个年龄的用户信息

    9、queryString查询

    10、重建索引

    10.1、创建test_index_v1索引、添加数据

    10.2、业务变更,字段类型需要变动

    10.3、 新建索引库 :test_index_v2

    10.4、将test_index_v1 数据拷贝到 test_index_v2

    11、别名的使用

    11.1、查询别名

    11.2、新增别名

    11.3、删除别名

    11.4、重命名别名

    11.5、为多个索引指定一个别名

    11.6、为同个索引指定多个别名 

    11.7、通过别名读索引

     11.8、通过别名写索引



    1、Restfull

            Elasticsearch默认走的是http协议,而http协议它是一种无状态的协议,无状态就是指服务端它不会记录客户端的所有信息和操作,客户端必须每次带上自己的状态去请求服务器。因此,如果客户端想要操作这个服务器,必须通过某些手段,才能让服务器发生状态转化。而这种转化是建立在表现层之上的,所以说这就表现层的状态转化。

    转化手段:

    1. GET:用来获取资源
    2. POST:用来创建资源(也可以用来更新资源)
    3. PUT:用来更新资源
    4. DELETE:用来删除资源

    我们对ES的所有操作,都被封装成了RestAPI,所以我们只要发送请求就行了。

    2、查看ES的基本信息

    2.1、查看集群信息

    查看所有结点GET _cat/nodes

    查看ES健康状况GET _cat/health

    • Green:主分片与副本都正常分配
    • Yellow:主分片全部正常分配,有副本分片未能正常分配
    • Red:有主分片未能分配

    查看主节点GET _cat/master

    查看所有索引:[类似于show databases] GET _cat/indices 

    以上查询带上参数 ?v可以显示标题信息,如:

    3、索引操作

    3.1、创建并显示指定索引字段的类型

    1. PUT user
    2. {
    3. "mappings": {
    4. "properties": {
    5. "name": {
    6. "type": "text",
    7. "fields": {
    8. "keyword": {
    9. "type": "keyword",
    10. "ignore_above": 256
    11. }
    12. }
    13. },
    14. "address": {
    15. "type": "text",
    16. "fields": {
    17. "keyword": {
    18. "type": "keyword",
    19. "ignore_above": 256
    20. }
    21. }
    22. },
    23. "remark": {
    24. "type": "text",
    25. "fields": {
    26. "keyword": {
    27. "type": "keyword"
    28. }
    29. }
    30. },
    31. "age": {
    32. "type": "long"
    33. },
    34. "salary": {
    35. "type": "double"
    36. },
    37. "birthDate": {
    38. "type": "date",
    39. "format": "yyyy-MM-dd"
    40. }
    41. }
    42. }
    43. }

    3.2、通过创建文档的方式自动映射字段的类型

            创建文件时,当索引不存在的时候会自动创建并且字段类型自动根据值进行映射。

    格式:PUT /索引名/类型名/文档id

    6.x的写法是:{index}/{type}/{id},例如:user/_doc/1 

    7.x的写法是:{index}/_doc/{id},例如:user/_doc/1

    在6.x中一个index中type只能有一个,可以自定义;

    在7.x中将type概念移除了,所以现在建议直接写成_doc,当然你硬要指定type类型也行,只是ES是给出一个警告。

    创建文档,并自动生成index。示例如下:

    1. PUT user/_doc/1
    2. {
    3. "name":"小白学es",
    4. "age":3
    5. }
    6. 如果索引原本中没有的字段,这是也会自动加上并且映射类型,比如之前是没有sex字段的。
    7. PUT /user/_doc/1
    8. {
    9. "name":"小白学es",
    10. "age":18,
    11. "sex":"男"
    12. }

    查看索引:GET user

    查看索引字段类型:GET user/_mapping

    删除索引:DELETE user

    4、文档操作:

    es使用版本:6.8.2

    4.1、增加文档信息

    未指定文档id时,创建文档,只能用POST(创建或更新)。

    1. POST /user/_doc
    2. {
    3. "name": "张三",
    4. "age": 29,
    5. "salary": 100,
    6. "address": "北京市",
    7. "remark": "来自中国北京市的张先生",
    8. "birthDate": "1990-01-10"
    9. }

     说明:上面的红色报警信息,是指6.x版本中默认分片为5,从7.x开始,默认分片为1,如果要更改,需要自己创建索引,或使用索引模板。

    增加文档时指定ID:该操作为更新操作,可以使用PUT(更新)POST(创建或更新)

    1. POST /user/_doc/1
    2. {
    3. "name": "张三",
    4. "age": 29,
    5. "salary": 100,
    6. "address": "北京市",
    7. "remark": "来自中国北京市的张先生",
    8. "birthDate": "1990-01-10"
    9. }

    4.2、更新文档信息

            更新文档信息可以使用PUT和POST来请求。

            PUT修改:全量字段更新。-- 覆盖式修改

            POST修改:指定字段更新(推荐使用)。

    指定字段更新的命令:

            

    1. POST /user/_doc/1/_update
    2. {
    3. "doc": {
    4. "name": "王五"
    5. }
    6. }

    使用PUT方式更新之前创建的 id=1 的文档信息。

    1. PUT /user/_doc/1
    2. {
    3. "name": "李四"
    4. }

     可以发现这里只更新了name字段,没有更新其它的字段,所以其它字段默认会填充空值。

    使用POST请求修改文档:

    首先将没个字段的值都初始化

    1. POST /user/_doc/1
    2. {
    3. "name": "张三",
    4. "age": 29,
    5. "salary": 100,
    6. "address": "北京市",
    7. "remark": "来自中国北京市的张先生",
    8. "birthDate": "1990-01-10"
    9. }

    然后再用POST请求执行修改文档操作:

    POST方式第一种更新:

    1. POST /user/_doc/1/_update
    2. {
    3. "doc": {
    4. "name": "王五"
    5. }
    6. }

    第一次执行结果:

      第二次执行结果:

             使用这种更新操作进行重复更新时,若数据与原先一致,则不进行任何操作。返回的结果是:"result": "noop",而不是"result" : "updated"。

      执行后的数据:

    POST方式第二种更新: 

    1. POST /user/_doc/1
    2. {
    3. "name":"赵六"
    4. }

    第一次执行结果:

     执行后的数据:

    第二次执行结果:

             使用第二种更新操作时[即不带_update],无论是否重复更新,数据是否一致,都会进行更新,version版本相应增加。因此若使用PUT方式,结果也一致。

    4.3、获取文档信息

            获取 user的索引 id=1 的文档信息。

    GET /user/_doc/1
    

            查询文档数量

    GET user/_doc/_count   

    4.4、删除文档信息

            删除之前创建的 id=1 的文档信息。

    DELETE /user/_doc/1

             根据查询语句删除:        

    1. # 根据查询语句删除
    2. POST /my-index/_delete_by_query
    3. {
    4. "query": {
    5. "match": {
    6. "user.id": "elkbee"
    7. }
    8. }
    9. }

            删除所有数据:

    1. #删除所有数据
    2. POST /my-index/_delete_by_query
    3. {
    4. "query": {
    5. "match_all": {}
    6. }
    7. }

    5、批量操作 

            有些情况下可以通过批量操作以减少网络请求。如:批量查询、批量插入数据等。

    在Elasticsearch中,支持批量的插入、修改、删除操作,都是通过_bulk的api完成的。

    _bulk分类:

    行为解释
    create当文档不存在时创建之
    index创建新文档或替换已有文档
    update局部更新文档
    delete删除一个文档

    在索引、 创建、 更新或删除时必须指定文档的 _index 、 _type 、 _id 这些元数据(metadata)。

    5.1、批量查询

    1. POST user/_doc/_mget
    2. {
    3. "ids" : [ "1", "XkQdS4MByEXWPCdI40rO" ]
    4. }
    5. #批量查询还有如下写法:Ids 指定Id值查询
    6. GET user/_search
    7. {
    8. "query": {
    9. "ids": {
    10. "values": [ "1", "XkQdS4MByEXWPCdI40rO"]
    11. }
    12. }
    13. }

    5.2、批量插入数据

      请求格式如下:

    1. { action: { metadata }}
    2. { request body }
    3. { action: { metadata }}
    4. { request body }
    5. ...

            需要注意的是,每一条数据都由两行构成(delete除外),其他的命令比如index和create都是由元信息行和数据行组成;update比较特殊它的数据行可能是doc也可能是upsert或者script。

            注意,每一行都是通过回车符来判断结束,因此如果你自己定义了json,千万不要使用回车符。不然_bulk命令会报错的!

    1. POST _bulk
    2. {"create":{"_index":"user","_type":"_doc","_id":2001}}
    3. {"name":"刘一","address":"广东省广州市花都区","remark":"公司底层码农员工","age":30,"salary":3000,"birthDate":"1989-11-11"}
    4. {"create":{"_index":"user","_type":"_doc","_id":2002}}
    5. {"name":"陈二","address":"广东省广州市花都区","remark":"公司底层码农员工","age":27,"salary":7900,"birthDate":"1992-01-25"}
    6. {"create":{"_index":"user","_type":"_doc","_id":2003}}
    7. {"name":"张三","address":"广东省广州市花都区","remark":"公司底层码农员工","age":28,"salary":8800,"birthDate":"1991-10-05"}
    8. {"create":{"_index":"user","_type":"_doc","_id":2004}}
    9. {"name":"李四","address":"广东省广州市花都区","remark":"公司底层码农员工","age":26,"salary":9000,"birthDate":"1993-08-18"}
    10. {"create":{"_index":"user","_type":"_doc","_id":2005}}
    11. {"name":"王五","address":"广东省广州市花都区","remark":"公司底层码农员工","age":31,"salary":4800,"birthDate":"1988-07-20"}

    5.3、批量删除:

    _delete_by_query :通过查询删除,既先query出符合条件的内容再进行delete操作.

    1. # 批量操作,同一批次中可以有 create、update、delete
    2. POST _bulk
    3. {"delete":{"_index":"user","_type":"_doc","_id":2001}}
    4. {"delete":{"_index":"user","_type":"_doc","_id":2002}}
    5. {"delete":{"_index":"user","_type":"_doc","_id":2003}}
    6. # 根据查询结果批量删除
    7. POST user/_doc/_delete_by_query
    8. {
    9. "query": {
    10. "match": { "name": "程八"}
    11. }
    12. }

    5.4、批量更新

    可以通过ctx来获得_source_index_type_id_version_parent_timestamp_ttl等字段信息。

     update_by_query 顾名思义,通过查询更新,既先query出符合条件的内容再进行update操作,新增字段,修改字段值都可以满足

    1. # 批量更新数据
    2. POST user/_doc/_bulk
    3. {"update": {"_id": "XkQdS4MByEXWPCdI40rO"}}
    4. {"doc": {"name": "张三三"}}
    5. {"update": {"_id": "8"}}
    6. {"doc": {"name": "程巴巴"}}
    7. # 将salary为4800的数据, remark修改为“薪资4800”:
    8. POST user/_update_by_query
    9. {
    10. "script": {
    11. "inline": "ctx._source.remark='薪资4800'"
    12. },
    13. "query": {
    14. "term": {
    15. "salary": {
    16. "value": "4800"
    17. }
    18. }
    19. }
    20. }

    6、查询数据

    在查询命令后拼上 ?pretty ,可以将返回结果进行格式化。

    6.1、查询所有文档信息

    GET user/_search

    6.2、根据关键字查询文档信息

            注意:text类型可以根据字段分词搜索,keyword关键词不会处理分词器

    1. #在所有字段中搜索字符串 “guide” 的基本匹配查询:
    2. # 该命令暂时报错
    3. GET /twitter/_search?q=guide
    4. #指定字段查询
    5. # 该命令暂时报错
    6. GET /user/_search?q=name:张三
    7. # 配合 from 来进行分页
    8. GET /user/_search?size=2&from=2

    6.3、匹配查询(match)

            会对搜索词进行分词拆解,然后查询,求并集。

             match是经过analyer的,也就是说,文档首先被分析器给处理了。根据不同的分析器,分析的结果也稍显不同,然后再根据分词结果进行匹配。   

    match 查询语法汇总:

    1. match_all:查询全部。
    2. match:返回所有匹配的分词。
    3. match_phrase:短语查询,在match的基础上进一步查询词组,可以指定slop分词间隔。
    4. match_phrase_prefix:前缀查询,根据短语中最后一个词组做前缀匹配,可以应用于搜索提示,但注意和max_expanions搭配。其实默认是50.......
    5. multi_match:多字段查询,使用相当的灵活,可以完成match_phrase和match_phrase_prefix的工作。

    Match中的模糊匹配与强制匹配 : ‘operator’

    • or :匹配单个或多个字符 ,不区分大小写,不区分顺序。默认operator为OR。
    • and :必须全匹配。

    设置参数 minimum_should_match 来设置至少匹配的数量。

     6.3.1、单字段匹配查询

    1. GET /user/_search
    2. {
    3. "query":{
    4. "match_all":{
    5. }
    6. }
    7. }
    8. # 查看name字段有"张三"的数据
    9. GET /user/_search
    10. {
    11. "query":{
    12. "match": {
    13. "name": "张三"
    14. }
    15. }
    16. }
    17. # 查看所有字段有"花都区" 的数据
    18. GET /user/_search
    19. {
    20. "query":{
    21. "multi_match": {
    22. "query": "花都区"
    23. }
    24. }
    25. }
    26. # 查看address字段有"广州"or"市"的数据
    27. GET /user/_search
    28. {
    29. "query": {
    30. "match": {
    31. "address": {
    32. "query": "广州市",
    33. "analyzer": "standard"
    34. }
    35. }
    36. }
    37. }
    38. #如下至少要匹配“北”,“京”,“市”,“的” ,“z” ,"先"及 “生” 这7个中的5个字才可以
    39. GET user/_search
    40. {
    41. "query": {
    42. "match": {
    43. "remark": {
    44. "query": "北京市的z先生",
    45. "operator": "or",
    46. "minimum_should_match": 5
    47. }
    48. }
    49. }
    50. }

     6.3.2、多字段匹配查询:

    1. # 查询 address 包含广东省 并且年龄在26-27的数据
    2. GET user/_doc/_search
    3. {
    4. "query": {
    5. "bool": {
    6. "must": [
    7. {
    8. "match": {"address": "广东省"}
    9. },
    10. {
    11. "range": { "age": {"gte": 26,"lte": 37}}
    12. }
    13. ]
    14. }
    15. }
    16. }

    6.4、顺序匹配(Match_phrase)

           会对搜索词进行分词拆解

            match_phrase与match 类似,但是match 查询时不用分先后顺序的,match_phrase 严格按顺序匹配。先将查询条件进行分词,然后查询.

    1. # 查询remark中包含“张先生北京市的” 分词后的信息 数据。
    2. GET user/_search
    3. {
    4. "query": {
    5. "match": {
    6. "remark": {
    7. "query": "张先生北京市的"
    8. }
    9. }
    10. }
    11. }
    12. # 查询remark中包含“北京市的张先生” 分词后 顺序必须一致的 数据。
    13. GET user/_search
    14. {
    15. "query": {
    16. "match_phrase": {
    17. "remark": {
    18. "query": "北京市的张先生"
    19. }
    20. }
    21. }
    22. }

    6.5、多字段查询(multi_match)

            会对搜索词进行分词拆解。

             multi_match:不知道哪个字段含有 指定关键词,在这种情况下,我们可以使用 multi_match 来进行搜索。

    1. # 查询 name or remark 含有 “北京市”的数据
    2. GET /user/_search/
    3. {
    4. "query": {
    5. "multi_match": {
    6. "query": "北京市",
    7. "fields": [
    8. "name",
    9. "remark"
    10. ]
    11. }
    12. }
    13. }

    6.6、精确匹配(term)

    关于查询过滤条件中term和match的区别
    term是代表完全匹配,也就是精确查询,搜索前不会再对搜索词进行分词拆解
    match进行搜索的时候,会先进行分词拆分,拆完后,再来匹配。

    1. # term 查询被用于精确值 匹配,
    2. # 这些精确值可能是数字、时间、布尔或者那些未分词的字符串(keyword)
    3. GET /user/_search/
    4. {
    5. "query":{
    6. "term":{
    7. "age":"26"
    8. }
    9. }
    10. }
    11. # term只能完整值匹配,这样就查询不出来
    12. GET /user/_doc/_search/
    13. {
    14. "query":{
    15. "term":{
    16. "salary":"9000"
    17. }
    18. }
    19. }
    20. #对于未分词的字符串查找
    21. GET /user/_search/
    22. {
    23. "query":{
    24. "term":{
    25. "name.keyword":"张三"
    26. }
    27. }
    28. }

    6.7、多词条精确匹配(terms) 

            不会再对搜索词进行分词拆解

            terms查询:terms 跟 term 有点类似,但 terms 允许指定多个匹配条件。 如果某个字段指定了多个值,那么文档需要一起去 做匹配。

            terms里的[ ] 多个是or的关系,只要满足其中一个词就可以。

            在这里我们使用了name.keyword。对于一些刚接触 Elasticsearch的人来说,这个可能比较陌生。正确的理解是 name在我们的 mapping 中是一个 multi-field 项。它既是 text 也是 keyword 类型。对于一个 keyword 类型的项来说,这个项里面的所有字符都被当做一个字符串。它们在建立文档时,不需要进行 index。keyword 字段用于精确搜索,聚合 和 排序(sorting)。keyword会使返回结果的_score 项为0。

    1. #terms里的[ ] 多个是or的关系,只要满足其中一个词就可以
    2. GET /user/_search
    3. {
    4. "query":{
    5. "terms":{
    6. "name.keyword":["张三","赵六1"]
    7. }
    8. }
    9. }
    10. #想要同时满足两个词的话,就得使用bool的must来做,如下
    11. GET /user/_search
    12. {
    13. "query": {
    14. "bool": {
    15. "must": [
    16. {
    17. "term": {
    18. "name.keyword": "张三"
    19. }
    20. },
    21. {
    22. "term": {
    23. "address.keyword": "北京市"
    24. }
    25. }
    26. ]
    27. }
    28. }
    29. }

    6.8、指定匹配数组内容(Terms_set)

    测试数据如下:

    1. PUT /job-candidates
    2. {
    3. "mappings": {
    4. "properties": {
    5. "name": {
    6. "type": "keyword"
    7. },
    8. "programming_languages": {
    9. "type": "keyword"
    10. },
    11. "required_matches": {
    12. "type": "long"
    13. }
    14. }
    15. }
    16. }
    17. PUT /job-candidates/_doc/1?refresh
    18. {
    19. "name": "Jane Smith",
    20. "programming_languages": [ "c++", "java" ],
    21. "required_matches": 2
    22. }
    23. PUT /job-candidates/_doc/2?refresh
    24. {
    25. "name": "Jason Response",
    26. "programming_languages": [ "java", "php" ],
    27. "required_matches": 2
    28. }

            refresh : 数据插入立即生效可以使更改可见以进行搜索的操作。通常会有一个 refresh timer 来定时完成这个操作。这个周期为1秒。这也是我们通常所说的 Elasticsearch 可以实现秒级的搜索。当然这个 timer 的周期也可以在索引的设置中进行配置。如果我们想让我们的结果马上可以对搜索可见,我们可以用refresh=true。

    测试案例:

            找出在 programming_languages 中同时含有 c++, java 以及 php 中至少有两项的文档。在这里,我们使用了一个在文档中定义的字段 required_matches 来定义最少满足要求的 term 个数,这里只数组中任意搭配,只要满足数量即可:

    1. GET /job-candidates/_search
    2. {
    3. "query": {
    4. "terms_set": {
    5. "programming_languages": {
    6. "terms": [ "c++", "java", "php" ],
    7. "minimum_should_match_field": "required_matches"
    8. }
    9. }
    10. }
    11. }

    terms : 指定要满足的数组。
    minimum_should_match_field : 指定文档中条件的属性名。
    required_matches 在文档的值为2,所以指定该值最后结果就是最少满足‘terms’属性中的至少2个。

    如果没有一个专有的字段来定义满足条件的个数的话,可以再查询条件中自定义,示例如下:

    1. GET /job-candidates/_search
    2. {
    3. "query": {
    4. "terms_set": {
    5. "programming_languages": {
    6. "terms": [ "c++", "java", "php" ],
    7. "minimum_should_match_script": {
    8. "source": "2"
    9. }
    10. }
    11. }
    12. }
    13. }

    6.9、多条件复合查询

            复合查询指把很多个 leaf 查询组合起来从而形成更为复杂的查询。

            bool 查询由 下面的 must, must_not, should 及 filter 共同来组成的。你可以使用 minimum_should_match 参数指定返回的文档必须匹配的子句的数量或百分比。

    示例:

    1. POST _search
    2. {
    3. "query": {
    4. "bool" : {
    5. "must" : {
    6. "match": {"address": "广东" }
    7. },
    8. "filter": {
    9. "match" : { "address" : "广州市" }
    10. },
    11. "must_not" : {
    12. "range" : {
    13. "age" : { "gte" : 10, "lte" : 26 }
    14. }
    15. },
    16. "should" : [
    17. { "term" : { "name" : "张三" } },
    18. { "term" : { "name" : "赵六" } }
    19. ]
    20. }
    21. }
    22. }
    23. # 只搜索指定索引
    24. GET user/_doc/_search
    25. {
    26. "query": {
    27. "bool" : {
    28. "must" : {
    29. "match": {"address": "广东" }
    30. },
    31. "filter": {
    32. "match" : { "address" : "广州市" }
    33. },
    34. "must_not" : {
    35. "range" : {
    36. "age" : { "gte" : 10, "lte" : 26 }
    37. }
    38. },
    39. "should" : [
    40. { "term" : { "name" : "张三" } },
    41. { "term" : { "name" : "赵六" } }
    42. ]
    43. }
    44. }
    45. }

    说明:

    "query": {        
           "bool" : {

              "must" :     [],        //与 AND 等价。  单个条件使用{},多个条件使【】 .
              "must_not" :   [],   //与 NOT 等价 。 同上  
              "should" : [],         //与 OR  等价。   同上
              "filter":  []            //与must相同结果,但不会参与评分。同上
        }
     }

    must : 必须满足的条件,按相关性降序排序显示。
    must_not : 可以把一些满足条件的排出在外(not in )。
    should : 它表述“或”的意思,也就是有就更好,没有就算了。如果条件满足,其相关性会更高,那么搜索得到的结果会排在前面。
    filter : 与must相同表示满足条件,但不会参与评分。

    查询类型对 hits(即:查询结果) 及 _score(即:评分、相关度) 的影响

    查询类型影响 hits影响 _score
    mustYesYes
    must_notYesNo
    shouldNoYes
    filterYesNo

            should 只有在特殊的情况下才会影响 hits。在正常的情况下它不会影响搜索文档的个数。那么在哪些情况下会影响搜索的结果呢?这种情况就是针对只有 should 的搜索情况,也就是如果你在 bool query 里,不含有 must, must_not 及 filter 的情况下,一个或更多的 should 必须有一个匹配才会有结果。

    filter与must的区别 :

    • 同样是按条件匹配;
    • filter不统计相关度,must统计相关度;
    • must比filter计算更复杂,更耗时。

    6.10、查询子句

            返回与一个或多个包在一起的查询(称为查询子句或子句)匹配的文档。

            如果返回的文档与多个查询子句匹配,则 dis_max 查询为该文档分配来自任何匹配子句的最高相关性得分,并为任何其他匹配子查询分配平局打破增量。

    示例:

    1. GET user/_search
    2. {
    3. "query": {
    4. "dis_max": {
    5. "queries": [
    6. { "term" : { "name.keyword": "张三" } },
    7. { "match" : { "address": "北京市" } }
    8. ],
    9. "tie_breaker": 0.7
    10. }
    11. }
    12. }

    dis_max参数 :

    • queries :包含一个或者多个查询子句。返回的文档必须匹配其中的一个或者多个,如果文档匹配了多个,则返回最高得分。
    • tie_breaker :一个介于0~1.0之间的Float数,用于当文档匹配了多个查询子句时提升相关度分数。默认为0.0

            在上面的 dis_max 查询中,它将返回任何一个在 queries 中锁定的查询文档。每个匹配分数是按照如下的规则来进行计算的:

    1. 如果一个文档匹配其中的一个或多个查询,那么最终的得分将以其中最高的那个得分来进行计算。
    2. 在默认的情况下,tie_breaker 的值为0。它可以是 0 到 1.0 之间的数。

    如果文档匹配多个子句,则 dis_max 查询将计算该文档的相关性得分,如下所示:

    1. 从具有最高分数的匹配子句中获取相关性分数。
    2. 将来自其他任何匹配子句的得分乘以 tie_breaker 值。
    3. 将最高分数加到相乘的分数上。

    如果 tie_breaker 值大于0.0,则所有匹配子句均计数,但得分最高的子句计数最高。

    6.11、SQL 查询

    Elasticsearch 也对 SQL 有支持,示例如下:

    1. GET _xpack/sql?pretty
    2. {
    3. "query": """
    4. SELECT * FROM user
    5. WHERE age > 25
    6. """
    7. }

    返回结果:

    可以通过如下的方法得到它对应的 DSL 语句(即es的查询语句): 

    1. GET _xpack/sql/translate
    2. {
    3. "query": """
    4. SELECT * FROM user
    5. WHERE age > 25
    6. """
    7. }

    返回结果如下:

    1. {
    2. "size" : 1000,
    3. "query" : {
    4. "range" : {
    5. "age" : {
    6. "from" : 25,
    7. "to" : null,
    8. "include_lower" : false,
    9. "include_upper" : false,
    10. "boost" : 1.0
    11. }
    12. }
    13. },
    14. "_source" : {
    15. "includes" : [
    16. "address",
    17. "name",
    18. "remark"
    19. ],
    20. "excludes" : [ ]
    21. },
    22. "docvalue_fields" : [
    23. {
    24. "field" : "age",
    25. "format" : "use_field_mapping"
    26. },
    27. {
    28. "field" : "birthDate",
    29. "format" : "epoch_millis"
    30. },
    31. {
    32. "field" : "salary",
    33. "format" : "use_field_mapping"
    34. }
    35. ],
    36. "sort" : [
    37. {
    38. "_doc" : {
    39. "order" : "asc"
    40. }
    41. }
    42. ]
    43. }

    6.12、Range 范围查询与 Sort 排序

    range : 查询范围
    sort : 可以针对多个字段同时进行排序。下面首先以 age 进行降序排序。如果是 age 是一样的话,那么就按照salary来进行排序。

    1. # 查看年龄大于26小于29的 数据,并根据 age、salary 排序
    2. GET user/_search
    3. {
    4. "query": {
    5. "range": {
    6. "age": {
    7. "gte": 26,
    8. "lte": 29
    9. }
    10. },
    11. "sort": [
    12. {
    13. "age": {
    14. "order": "desc"
    15. }
    16. },
    17. {
    18. "salary": {
    19. "order": "asc"
    20. }
    21. }
    22. ]
    23. }
    24. }

    6.13、通配符查询(Wildcard)

    不会对搜索词进行分词拆解。

    可以使用 wildcard 查询一个字符串里含有的字符:

    • ? 匹配任何字符,
    • * 匹配零个或多个字符
    1. # 查询name为*三 的数据
    2. GET user/_doc/_search
    3. {
    4. "query":{
    5. "wildcard":{
    6. "name":"*三"
    7. }
    8. }
    9. }

    6.14、指定Id值查询(Ids)

    1. # Ids 指定Id值查询
    2. GET user/_search
    3. {
    4. "query": {
    5. "ids": {
    6. "values": [ "1", "XkQdS4MByEXWPCdI40rO"]
    7. }
    8. }
    9. }

    6.15、以特定前缀开头(Prefix)

    不会对搜索词进行分词拆解。

    1. # 查询 name 以“张” 开头的数据
    2. GET user/_search
    3. {
    4. "query": {
    5. "prefix": {
    6. "name": {
    7. "value": "张"
    8. }
    9. }
    10. }
    11. }

    6.16、多查询一次提交(Msearch)

    示例:

    1. GET user/_msearch
    2. {"index":"user"}
    3. {"query":{"match_all":{}},"from":0,"size":1}
    4. {"index":"user"}
    5. {"query":{"bool":{"filter":{"term":{"name.keyword":"张三"}}}}, "size":1}
    6. {"index":"user"}
    7. {"query":{"match_all":{}}}

            会将多个查询一并提交,一并返回结果,一个查询报错不会影响另一个结果 。以上查询返回结果如下:

    1. {
    2. "responses" : [
    3. {
    4. "took" : 1,
    5. "timed_out" : false,
    6. "_shards" : {
    7. "total" : 5,
    8. "successful" : 5,
    9. "skipped" : 0,
    10. "failed" : 0
    11. },
    12. "hits" : {
    13. "total" : 4,
    14. "max_score" : 1.0,
    15. "hits" : [
    16. {
    17. "_index" : "user",
    18. "_type" : "_doc",
    19. "_id" : "2004",
    20. "_score" : 1.0,
    21. "_source" : {
    22. "name" : "李四",
    23. "address" : "广东省广州市花都区",
    24. "remark" : "公司底层码农员工",
    25. "age" : 26,
    26. "salary" : 9000,
    27. "birthDate" : "1993-08-18"
    28. }
    29. }
    30. ]
    31. },
    32. "status" : 200
    33. },
    34. {
    35. "took" : 0,
    36. "timed_out" : false,
    37. "_shards" : {
    38. "total" : 5,
    39. "successful" : 5,
    40. "skipped" : 0,
    41. "failed" : 0
    42. },
    43. "hits" : {
    44. "total" : 1,
    45. "max_score" : 0.0,
    46. "hits" : [
    47. {
    48. "_index" : "user",
    49. "_type" : "_doc",
    50. "_id" : "XkQdS4MByEXWPCdI40rO",
    51. "_score" : 0.0,
    52. "_source" : {
    53. "name" : "张三",
    54. "age" : 29,
    55. "salary" : 100,
    56. "address" : "北京市",
    57. "remark" : "来自中国北京市的张先生",
    58. "birthDate" : "1990-01-10"
    59. }
    60. }
    61. ]
    62. },
    63. "status" : 200
    64. },
    65. {
    66. "took" : 0,
    67. "timed_out" : false,
    68. "_shards" : {
    69. "total" : 5,
    70. "successful" : 5,
    71. "skipped" : 0,
    72. "failed" : 0
    73. },
    74. "hits" : {
    75. "total" : 4,
    76. "max_score" : 1.0,
    77. "hits" : [
    78. {
    79. "_index" : "user",
    80. "_type" : "_doc",
    81. "_id" : "2004",
    82. "_score" : 1.0,
    83. "_source" : {
    84. "name" : "李四",
    85. "address" : "广东省广州市花都区",
    86. "remark" : "公司底层码农员工",
    87. "age" : 26,
    88. "salary" : 9000,
    89. "birthDate" : "1993-08-18"
    90. }
    91. },
    92. {
    93. "_index" : "user",
    94. "_type" : "_doc",
    95. "_id" : "2005",
    96. "_score" : 1.0,
    97. "_source" : {
    98. "name" : "王五",
    99. "address" : "广东省广州市花都区",
    100. "remark" : "公司底层码农员工",
    101. "age" : 31,
    102. "salary" : 4800,
    103. "birthDate" : "1988-07-20"
    104. }
    105. },
    106. {
    107. "_index" : "user",
    108. "_type" : "_doc",
    109. "_id" : "1",
    110. "_score" : 1.0,
    111. "_source" : {
    112. "name" : "赵六"
    113. }
    114. },
    115. {
    116. "_index" : "user",
    117. "_type" : "_doc",
    118. "_id" : "XkQdS4MByEXWPCdI40rO",
    119. "_score" : 1.0,
    120. "_source" : {
    121. "name" : "张三",
    122. "age" : 29,
    123. "salary" : 100,
    124. "address" : "北京市",
    125. "remark" : "来自中国北京市的张先生",
    126. "birthDate" : "1990-01-10"
    127. }
    128. }
    129. ]
    130. },
    131. "status" : 200
    132. }
    133. ]
    134. }

    6.17、查询字段是否存在(Exists)

            查询文档中包含address字段的所有文档信息。示例如下:

            文档里只要address这个字段不为空,那么就会被返回。反之,如果一个文档里address这个字段是空的,那么就不会返回。

    1. # 查询文档中包含address字段的所有文档
    2. GET user/_search
    3. {
    4. "query": {
    5. "exists": {
    6. "field": "address"
    7. }
    8. }
    9. }

            查询文档不含address 这个字段的所有的文档,可以这样查询 :

            注:插入时指定字段值为null,那么exists也会过滤掉。

    1. # 查询文档不含address 这个字段的所有的文档
    2. GET user/_search
    3. {
    4. "query": {
    5. "bool": {
    6. "must_not": {
    7. "exists": {
    8. "field": "address"
    9. }
    10. }
    11. }
    12. }
    13. }

    6.18、控制输出的的字段

    正常的查询结果(不控制出参字段)如下:

    1. {
    2. "took" : 1,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 1,
    12. "max_score" : 0.97997844,
    13. "hits" : [
    14. {
    15. "_index" : "user",
    16. "_type" : "_doc",
    17. "_id" : "2005",
    18. "_score" : 0.97997844,
    19. "_source" : {
    20. "name" : "王五",
    21. "address" : "广东省广州市花都区",
    22. "remark" : "公司底层码农员工",
    23. "age" : 31,
    24. "salary" : 4800,
    25. "birthDate" : "1988-07-20"
    26. }
    27. }
    28. ]
    29. }
    30. }

    6.18.1、通过 filter_path 来控制输出的的字段 

    1. #通过 filter_path 来控制输出的的字段
    2. GET user/_search?filter_path=hits.hits._score,hits.hits._source.name

    返回结果如下:

    1. {
    2. "hits" : {
    3. "hits" : [
    4. {
    5. "_score" : 1.0,
    6. "_source" : {
    7. "name" : "李四"
    8. }
    9. },
    10. {
    11. "_score" : 1.0,
    12. "_source" : {
    13. "name" : "王五"
    14. }
    15. },
    16. {
    17. "_score" : 1.0,
    18. "_source" : {
    19. "name" : "赵六"
    20. }
    21. },
    22. {
    23. "_score" : 1.0,
    24. "_source" : {
    25. "name" : "张三"
    26. }
    27. }
    28. ]
    29. }
    30. }

     6.18.2、通过 _source来控制输出字段

            _source 设置为[] {} 那么就是显示所有的字段

    1. #通过 _source来控制输出的的字段
    2. GET user/_doc/_search
    3. {
    4. "_source": ["age", "name","address"],
    5. "query": {
    6. "bool": {
    7. "must": [
    8. {
    9. "match": {"address": "北京"}
    10. }
    11. ]
    12. }
    13. }
    14. }

    查询结果如下:

    1. {
    2. "took" : 1,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 1,
    12. "max_score" : 0.5753642,
    13. "hits" : [
    14. {
    15. "_index" : "user",
    16. "_type" : "_doc",
    17. "_id" : "XkQdS4MByEXWPCdI40rO",
    18. "_score" : 0.5753642,
    19. "_source" : {
    20. "address" : "北京市",
    21. "name" : "张三",
    22. "age" : 29
    23. }
    24. }
    25. ]
    26. }
    27. }

    6.18.3、通过 _source 中的 includes 属性来控制输出字段

    1. #通过 _source 中的 includes 属性
    2. GET user/_search
    3. {
    4. "_source": {
    5. "includes": ["name", "address","birthDate"]
    6. },
    7. "query": {
    8. "bool": {
    9. "must": [
    10. {
    11. "match": {"address": "北京"}
    12. }
    13. ]
    14. }
    15. }
    16. }

    查询结果如下:

    1. {
    2. "took" : 1,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 1,
    12. "max_score" : 0.5753642,
    13. "hits" : [
    14. {
    15. "_index" : "user",
    16. "_type" : "_doc",
    17. "_id" : "XkQdS4MByEXWPCdI40rO",
    18. "_score" : 0.5753642,
    19. "_source" : {
    20. "address" : "北京市",
    21. "name" : "张三",
    22. "birthDate" : "1990-01-10"
    23. }
    24. }
    25. ]
    26. }
    27. }

     6.18.4、通过 _source 中的 exclude属性排除指定字段输出(exclude后续版本已弃用)

    1. #通过 _source 中的 exclude属性排除指定字段输出
    2. GET user/_search
    3. {
    4. "_source": {
    5. "exclude": ["birthDate","age"]
    6. },
    7. "query": {
    8. "bool": {
    9. "must": [
    10. {
    11. "match": {"address": "北京"}
    12. }
    13. ]
    14. }
    15. }
    16. }

    查询结果:

    1. #! Deprecation: Deprecated field [exclude] used, expected [excludes] instead
    2. {
    3. "took" : 1,
    4. "timed_out" : false,
    5. "_shards" : {
    6. "total" : 5,
    7. "successful" : 5,
    8. "skipped" : 0,
    9. "failed" : 0
    10. },
    11. "hits" : {
    12. "total" : 1,
    13. "max_score" : 0.5753642,
    14. "hits" : [
    15. {
    16. "_index" : "user",
    17. "_type" : "_doc",
    18. "_id" : "XkQdS4MByEXWPCdI40rO",
    19. "_score" : 0.5753642,
    20. "_source" : {
    21. "address" : "北京市",
    22. "name" : "张三",
    23. "remark" : "来自中国北京市的张先生",
    24. "salary" : 100
    25. }
    26. }
    27. ]
    28. }
    29. }

    6.18.5、设置 _source 为 false,这样不返回任何的 _source 信息:

    1. #设置 _source 为 false,这样不返回任何的 _source 信息
    2. GET user/_doc/_search
    3. {
    4. "_source":false,
    5. "query": {
    6. "bool": {
    7. "must": [
    8. {
    9. "match": {"address": "北京"}
    10. }
    11. ]
    12. }
    13. }
    14. }

    查询结果:

    1. {
    2. "took" : 0,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 1,
    12. "max_score" : 0.5753642,
    13. "hits" : [
    14. {
    15. "_index" : "user",
    16. "_type" : "_doc",
    17. "_id" : "XkQdS4MByEXWPCdI40rO",
    18. "_score" : 0.5753642
    19. }
    20. ]
    21. }
    22. }

     6.19、分页查询

            这里的分页查询和mysql中的分页查询操作本质上是没有区别的,是只要规定我们的起始点以及页的大小即可。

    1. GET user/_doc/_search
    2. {
    3. "query": {
    4. "match_all":{}
    5. }
    6. , "from": 0
    7. , "size": 2
    8. }

    查询结果:

            总数据量是4条,但是这里我们查询出来只显示了前面的两条数据,显然分页查询已经执行成功。

    1. {
    2. "took" : 2,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 4,
    12. "max_score" : 1.0,
    13. "hits" : [
    14. {
    15. "_index" : "user",
    16. "_type" : "_doc",
    17. "_id" : "2004",
    18. "_score" : 1.0,
    19. "_source" : {
    20. "name" : "李四",
    21. "address" : "广东省广州市花都区",
    22. "remark" : "公司底层码农员工",
    23. "age" : 26,
    24. "salary" : 9000,
    25. "birthDate" : "1993-08-18"
    26. }
    27. },
    28. {
    29. "_index" : "user",
    30. "_type" : "_doc",
    31. "_id" : "2005",
    32. "_score" : 1.0,
    33. "_source" : {
    34. "name" : "王五",
    35. "address" : "广东省广州市花都区",
    36. "remark" : "公司底层码农员工",
    37. "age" : 31,
    38. "salary" : 4800,
    39. "birthDate" : "1988-07-20"
    40. }
    41. }
    42. ]
    43. }
    44. }

    6.20、高亮查询

            我们平时在使用百度的时候,输入关键字查询内容后,关键字一般都是高亮显示的。所以ES作为一个专业的搜索框架肯定也提供了这样的功能。

            ES的默认高亮显示:。

    如:

    1. GET /user/_search
    2. {
    3. "query": {
    4. "match": {
    5. "name": "李四"
    6. }
    7. },
    8. "highlight": {
    9. "fields": {
    10. "name": {}
    11. }
    12. }
    13. }

       查询结果:

    1. {
    2. "took" : 92,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 1,
    12. "max_score" : 1.9616584,
    13. "hits" : [
    14. {
    15. "_index" : "user",
    16. "_type" : "_doc",
    17. "_id" : "2004",
    18. "_score" : 1.9616584,
    19. "_source" : {
    20. "name" : "李四",
    21. "address" : "广东省广州市花都区",
    22. "remark" : "公司底层码农员工",
    23. "age" : 26,
    24. "salary" : 9000,
    25. "birthDate" : "1993-08-18"
    26. },
    27. "highlight" : {
    28. "name" : [
    29. ""
    30. ]
    31. }
    32. }
    33. ]
    34. }
    35. }

            ES自定义高亮显示(在highlight中,pre_tags用来实现我们的自定义标签的前半部分,在这里,我们也可以为自定义的 标签添加属性和样式。post_tags实现标签的后半部分,组成一个完整的标签。至于标签中的内容,则还是交给fields来完成)

    1. GET /user/_search
    2. {
    3. "query": {
    4. "match": {
    5. "remark": "中国"
    6. }
    7. },
    8. "highlight": {
    9. "pre_tags": "",
    10. "post_tags": "",
    11. "fields": {
    12. "remark": {}
    13. }
    14. }
    15. }
    16. # 或者
    17. GET /user/_search
    18. {
    19. "query": {
    20. "match": {
    21. "remark": "中国"
    22. }
    23. },
    24. "highlight": {
    25. "fields": {
    26. "remark": {
    27. "pre_tags": "",
    28. "post_tags": ""
    29. }
    30. }
    31. }
    32. }

    查询结果如下:

    1. {
    2. "took" : 4,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 1,
    12. "max_score" : 0.5753642,
    13. "hits" : [
    14. {
    15. "_index" : "user",
    16. "_type" : "_doc",
    17. "_id" : "XkQdS4MByEXWPCdI40rO",
    18. "_score" : 0.5753642,
    19. "_source" : {
    20. "name" : "张三三",
    21. "age" : 29,
    22. "salary" : 100,
    23. "address" : "北京市",
    24. "remark" : "来自中国北京市的张先生",
    25. "birthDate" : "1990-01-10",
    26. "id" : "1"
    27. },
    28. "highlight" : {
    29. "remark" : [
    30. "来自北京市的张先生"
    31. ]
    32. }
    33. }
    34. ]
    35. }
    36. }

    7、Profile 调试工具

            会显示查询出结果的详细计算过程。

    1. GET user/_search
    2. {
    3. "profile": "true",
    4. "query": {
    5. "match_phrase": {
    6. "remark": {
    7. "query": "北京市的张先生"
    8. }
    9. }
    10. }
    11. }

    8、聚合查询

            我们平时在使用Elasticsearch时,更多会用到聚合操作,它类似SQL中的group by操作。ES的聚合查询一定是先查出结果,然后对结果使用聚合函数做处理,常用的操作有:avg:求平均、max:最大值、min:最小值、sum:求和等。

    在ES中聚合分为指标聚合和分桶聚合:

    • 指标聚合:对一个数据集求最大、最小、和、平均值等。
    • 分桶聚合:除了有聚合函数外,还可以对查询出的数据进行分组group by,再在组上进行游标聚合。

    8.1、指标聚合分析(Metric )

    指标聚合:对一个数据集求最大、最小、和、平均值等.

    • 单值分析,只输出一个分析结果——avg:求平均、max:最大值、min:最小值、sum:求和、cardinality:值去重计数。
    • 多值分析,输出多个分析结果
      • stats:统计了count 、max、 min、 avg、 sum  5个值。
      • extended_stats:比stats多很多更加高级的统计结果:如平方和、方差、标准差、平均值加/减两个标准差的区间等。
      • percentile占比百分位对应的值统计,默认返回【1,5,25,50,75,95,99】分位上的值

    8.1.1、avg示例:查询所有用户的平均年龄

    1. GET /user/_search
    2. {
    3. "query": {
    4. "match_all": {}
    5. },
    6. "aggs": {
    7. "avg_age": {
    8. "avg": {
    9. "field": "age"
    10. }
    11. }
    12. },
    13. "_source": [
    14. "name",
    15. "age"
    16. ]
    17. }

             上例中,首先匹配查询所有的数据。在此基础上做查询平均值的操作,这里就用到了聚合函数,其语法被封装在aggs中,而avg_age则是为查询结果起个别名,封装了计算出的平均值

    上面示例查询结果如下:

    1. {
    2. "took" : 1,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 4,
    12. "max_score" : 1.0,
    13. "hits" : [
    14. {
    15. "_index" : "user",
    16. "_type" : "_doc",
    17. "_id" : "8",
    18. "_score" : 1.0,
    19. "_source" : {
    20. "name" : "程巴巴"
    21. }
    22. },
    23. {
    24. "_index" : "user",
    25. "_type" : "_doc",
    26. "_id" : "2005",
    27. "_score" : 1.0,
    28. "_source" : {
    29. "name" : "王五",
    30. "age" : 31
    31. }
    32. },
    33. {
    34. "_index" : "user",
    35. "_type" : "_doc",
    36. "_id" : "2004",
    37. "_score" : 1.0,
    38. "_source" : {
    39. "name" : "李四",
    40. "age" : 26
    41. }
    42. },
    43. {
    44. "_index" : "user",
    45. "_type" : "_doc",
    46. "_id" : "XkQdS4MByEXWPCdI40rO",
    47. "_score" : 1.0,
    48. "_source" : {
    49. "name" : "张三三",
    50. "age" : 29
    51. }
    52. }
    53. ]
    54. },
    55. "aggregations" : {
    56. "avg_age" : {
    57. "value" : 28.666666666666668
    58. }
    59. }
    60. }

    如果只想看输出的值,而不关心输出的文档的话可以通过size=0来控制。

    1. # 只想看输出的值,而不关心输出的文档的话可以通过size=0来控制
    2. GET /user/_search
    3. {
    4. "query": {
    5. "match_all": {}
    6. },
    7. "aggs": {
    8. "avg_age": {
    9. "avg": {
    10. "field": "age"
    11. }
    12. }
    13. },
    14. "size": 0,
    15. "_source": [
    16. "name",
    17. "age"
    18. ]
    19. }

    查询结果如下:

    1. {
    2. "took" : 5,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 4,
    12. "max_score" : 0.0,
    13. "hits" : [ ]
    14. },
    15. "aggregations" : {
    16. "avg_age" : {
    17. "value" : 28.666666666666668
    18. }
    19. }
    20. }

    8.1.2、avg示例:查询地址在 “广东省”用户的平均工资

    1. #avg示例:查询地址在 “广东省”用户的平均工资
    2. GET /user/_search
    3. {
    4. "query": {
    5. "match_phrase": {
    6. "address": "广东省"
    7. }
    8. },
    9. "aggs": {
    10. "avg_salary": {
    11. "avg": {
    12. "field": "salary"
    13. }
    14. }
    15. },
    16. "size": 0
    17. }

    查询结果:

    1. {
    2. "took" : 3,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 2,
    12. "max_score" : 0.0,
    13. "hits" : [ ]
    14. },
    15. "aggregations" : {
    16. "avg_salary" : {
    17. "value" : 6900.0
    18. }
    19. }
    20. }

    8.1.3、max示例:查询年龄的最大值

    1. # max示例:查询年龄的最大值
    2. GET /user/_search
    3. {
    4. "query": {
    5. "match_all": {}
    6. },
    7. "aggs": {
    8. "max_age": {
    9. "max": {
    10. "field": "age"
    11. }
    12. }
    13. },
    14. "size": 0
    15. }

    查询结果:

    1. {
    2. "took" : 4,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 4,
    12. "max_score" : 0.0,
    13. "hits" : [ ]
    14. },
    15. "aggregations" : {
    16. "max_age" : {
    17. "value" : 31.0
    18. }
    19. }
    20. }

    8.1.4、min示例:查询年龄的最小值

    1. #min示例:查询年龄的最小值
    2. GET /user/_search
    3. {
    4. "query": {
    5. "match_all": {}
    6. },
    7. "aggs": {
    8. "min_age": {
    9. "min": {
    10. "field": "age"
    11. }
    12. }
    13. },
    14. "size": 0
    15. }

    查询结果:

    1. {
    2. "took" : 2,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 4,
    12. "max_score" : 0.0,
    13. "hits" : [ ]
    14. },
    15. "aggregations" : {
    16. "min_age" : {
    17. "value" : 26.0
    18. }
    19. }
    20. }

    8.1.5、sum示例:查询符合条件的年龄之和

    1. #sum示例:查询符合条件的年龄之和
    2. GET /user/_search
    3. {
    4. "query": {
    5. "match_all": {}
    6. },
    7. "aggs": {
    8. "sum_age": {
    9. "sum": {
    10. "field": "age"
    11. }
    12. }
    13. },
    14. "size": 0
    15. }

    查询结果:

    1. {
    2. "took" : 1,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 4,
    12. "max_score" : 0.0,
    13. "hits" : [ ]
    14. },
    15. "aggregations" : {
    16. "sum_age" : {
    17. "value" : 86.0
    18. }
    19. }
    20. }

    8.1.6、cardinality示例:查询所有用户不同年龄的数量

            cardinality 即去重计算,类似sql中 count(distinct),先去重再求和,计算指定field值的种类数。大数据量下,统计会存在误差。

            相同年龄的数据,count认为是1。

            在执行该示例前,专门添加了一条年龄为29的数据(原数据中已存在年龄29的数据)。

    1. 示例:查询所有用户不同年龄的数量
    2. GET /user/_search
    3. {
    4. "query": {
    5. "match_all": {}
    6. },
    7. "aggs": {
    8. "count_age": {
    9. "cardinality": {
    10. "field": "age"
    11. }
    12. }
    13. },
    14. "size": 0
    15. }

    查询结果:

    1. {
    2. "took" : 2,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 5,
    12. "max_score" : 0.0,
    13. "hits" : [ ]
    14. },
    15. "aggregations" : {
    16. "count_age" : {
    17. "value" : 3
    18. }
    19. }
    20. }

    8.1.7、stats示例:查出所有用户的年龄stats信息

    1. # stats示例:查出所有用户的年龄统计信息
    2. GET /user/_search
    3. {
    4. "query": {
    5. "match_all": {}
    6. },
    7. "aggs": {
    8. "stats_age": {
    9. "stats": {
    10. "field": "age"
    11. }
    12. }
    13. },
    14. "size": 0
    15. }

    查询结果:

    1. {
    2. "took" : 0,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 5,
    12. "max_score" : 0.0,
    13. "hits" : [ ]
    14. },
    15. "aggregations" : {
    16. "stats_age" : {
    17. "count" : 4,
    18. "min" : 26.0,
    19. "max" : 31.0,
    20. "avg" : 28.75,
    21. "sum" : 115.0
    22. }
    23. }
    24. }

    8.1.8、extended_stats示例:查出所有用户的年龄extended_stats信息

    1. #查出所有用户的年龄extended_stats信息
    2. GET /user/_search
    3. {
    4. "query": {
    5. "match_all": {}
    6. },
    7. "aggs": {
    8. "extended_stats_age": {
    9. "extended_stats": {
    10. "field": "age"
    11. }
    12. }
    13. },
    14. "size": 0
    15. }

    查询结果:

    1. {
    2. "took" : 1,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 5,
    12. "max_score" : 0.0,
    13. "hits" : [ ]
    14. },
    15. "aggregations" : {
    16. "extended_stats_age" : {
    17. "count" : 4,
    18. "min" : 26.0,
    19. "max" : 31.0,
    20. "avg" : 28.75,
    21. "sum" : 115.0,
    22. "sum_of_squares" : 3319.0,
    23. "variance" : 3.1875,
    24. "std_deviation" : 1.7853571071357126,
    25. "std_deviation_bounds" : {
    26. "upper" : 32.320714214271426,
    27. "lower" : 25.179285785728574
    28. }
    29. }
    30. }
    31. }

    8.1.9、percentile示例:查出所有用户的年龄占比

    1. # 查出所有用户的年龄占比
    2. POST /user/_search
    3. {
    4. "query": {
    5. "match_all": {}
    6. },
    7. "aggs": {
    8. "pecent_age": {
    9. "percentiles": {
    10. "field": "age"
    11. }
    12. }
    13. },
    14. "size": 0
    15. }

    查询结果:

    1. {
    2. "took" : 3,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 5,
    12. "max_score" : 0.0,
    13. "hits" : [ ]
    14. },
    15. "aggregations" : {
    16. "pecent_age" : {
    17. "values" : {
    18. "1.0" : 26.0,
    19. "5.0" : 26.0,
    20. "25.0" : 27.5,
    21. "50.0" : 29.0,
    22. "75.0" : 30.0,
    23. "95.0" : 31.0,
    24. "99.0" : 31.0
    25. }
    26. }
    27. }
    28. }

    8.2、Bucket 分桶聚合分析

            分桶聚合:除了有聚合函数外,还可以对查询出的数据进行分组group by,再在组上进行游标聚合。

      terms : 聚合分组,类似于sql中group by。

    8.2.1、分桶group by示例:根据年龄聚合查询

    1. # 根据年龄聚合查询
    2. GET /user/_search
    3. {
    4. "size": 0,
    5. "query": {
    6. "match_all": {}
    7. },
    8. "aggs": {
    9. "age_group": {
    10. "terms": {
    11. "field": "age"
    12. }
    13. }
    14. }
    15. }

    查询结果:

    1. {
    2. "took" : 6,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 5,
    12. "max_score" : 0.0,
    13. "hits" : [ ]
    14. },
    15. "aggregations" : {
    16. "age_group" : {
    17. "doc_count_error_upper_bound" : 0,
    18. "sum_other_doc_count" : 0,
    19. "buckets" : [
    20. {
    21. "key" : 29,
    22. "doc_count" : 2
    23. },
    24. {
    25. "key" : 26,
    26. "doc_count" : 1
    27. },
    28. {
    29. "key" : 31,
    30. "doc_count" : 1
    31. }
    32. ]
    33. }
    34. }
    35. }

    8.2.2、分桶group by示例:根据年龄段聚合查询

    1. #根据年龄段聚合查询
    2. GET /user/_search
    3. {
    4. "size": 0,
    5. "query": {
    6. "match_all": {}
    7. },
    8. "aggs": {
    9. "age_group": {
    10. "range": {
    11. "field": "age",
    12. "ranges": [
    13. {
    14. "from": 20,
    15. "to": 30
    16. },
    17. {
    18. "from": 30,
    19. "to": 40
    20. }
    21. ]
    22. }
    23. }
    24. }
    25. }

    查询结果:

    1. {
    2. "took" : 4,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 5,
    12. "max_score" : 0.0,
    13. "hits" : [ ]
    14. },
    15. "aggregations" : {
    16. "age_group" : {
    17. "buckets" : [
    18. {
    19. "key" : "20.0-30.0",
    20. "from" : 20.0,
    21. "to" : 30.0,
    22. "doc_count" : 3
    23. },
    24. {
    25. "key" : "30.0-40.0",
    26. "from" : 30.0,
    27. "to" : 40.0,
    28. "doc_count" : 1
    29. }
    30. ]
    31. }
    32. }
    33. }

    8.2.3、分桶group by示例:根据用户出生日期的年月分组分段聚合查询

    1. #根据用户出生日期的年月分组分段聚合查询
    2. POST /user/_search
    3. {
    4. "size": 0,
    5. "query": {
    6. "match_all": {}
    7. },
    8. "aggs": {
    9. "bithday_range": {
    10. "date_range": {
    11. "field": "birthDate",
    12. "format": "yyyy-MM",
    13. "ranges": [
    14. {
    15. "to": "1985-01"
    16. },
    17. {
    18. "from": "1985-01",
    19. "to": "1990-01"
    20. },
    21. {
    22. "from": "1990-01",
    23. "to": "1995-01"
    24. },
    25. {
    26. "from": "1995-01"
    27. }
    28. ]
    29. }
    30. }
    31. }
    32. }

    查询结果:

    1. #! Deprecation: 'y' year should be replaced with 'u'. Use 'y' for year-of-era. Prefix your date format with '8' to use the new specifier.
    2. {
    3. "took" : 2,
    4. "timed_out" : false,
    5. "_shards" : {
    6. "total" : 5,
    7. "successful" : 5,
    8. "skipped" : 0,
    9. "failed" : 0
    10. },
    11. "hits" : {
    12. "total" : 5,
    13. "max_score" : 0.0,
    14. "hits" : [ ]
    15. },
    16. "aggregations" : {
    17. "bithday_range" : {
    18. "buckets" : [
    19. {
    20. "key" : "*-1985-01",
    21. "to" : 4.733856E11,
    22. "to_as_string" : "1985-01",
    23. "doc_count" : 0
    24. },
    25. {
    26. "key" : "1985-01-1990-01",
    27. "from" : 4.733856E11,
    28. "from_as_string" : "1985-01",
    29. "to" : 6.31152E11,
    30. "to_as_string" : "1990-01",
    31. "doc_count" : 1
    32. },
    33. {
    34. "key" : "1990-01-1995-01",
    35. "from" : 6.31152E11,
    36. "from_as_string" : "1990-01",
    37. "to" : 7.889184E11,
    38. "to_as_string" : "1995-01",
    39. "doc_count" : 3
    40. },
    41. {
    42. "key" : "1995-01-*",
    43. "from" : 7.889184E11,
    44. "from_as_string" : "1995-01",
    45. "doc_count" : 0
    46. }
    47. ]
    48. }
    49. }
    50. }

    8.2.4、group by 进阶示例:按照年龄聚合,并查询出每个年龄这些人的平均薪资

            其实就是aggs里面又加了一个aggs,第二个aggs根据第一个aggs聚合后的结果在聚合。

    1. GET /user/_search
    2. {
    3. "query": {
    4. "match_all": {}
    5. },
    6. "aggs": {
    7. "ageAgg": {
    8. "terms": {
    9. "field": "age"
    10. },
    11. "aggs": {
    12. "ageAvg": {
    13. "avg": {
    14. "field": "salary"
    15. }
    16. }
    17. }
    18. }
    19. },
    20. "size": 0
    21. }

    查询结果:

    1. {
    2. "took" : 0,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 5,
    12. "max_score" : 0.0,
    13. "hits" : [ ]
    14. },
    15. "aggregations" : {
    16. "ageAgg" : {
    17. "doc_count_error_upper_bound" : 0,
    18. "sum_other_doc_count" : 0,
    19. "buckets" : [
    20. {
    21. "key" : 29,
    22. "doc_count" : 2,
    23. "ageAvg" : {
    24. "value" : 4500.0
    25. }
    26. },
    27. {
    28. "key" : 26,
    29. "doc_count" : 1,
    30. "ageAvg" : {
    31. "value" : 9000.0
    32. }
    33. },
    34. {
    35. "key" : 31,
    36. "doc_count" : 1,
    37. "ageAvg" : {
    38. "value" : 4800.0
    39. }
    40. }
    41. ]
    42. }
    43. }
    44. }

    8.2.5、group by 进阶示例:查出所有年龄分布,并且这些年龄段中 性别为男 的平均薪资和 性别为女 的平均薪资以及这个年龄的用户信息

    1. GET /user/_search
    2. {
    3. "query": {
    4. "match_all": {}
    5. },
    6. "size": 0,
    7. "aggs": {
    8. "age_agg": {
    9. "terms": {
    10. "field": "age",
    11. "size": 1000
    12. },
    13. "aggs": {
    14. "sex_agg": {
    15. "terms": {
    16. "field": "sex.keyword",
    17. "size": 10
    18. },
    19. "aggs": {
    20. "salary_avg": {
    21. "avg": {
    22. "field": "salary"
    23. }
    24. }
    25. }
    26. },
    27. "salary_avg": {
    28. "avg": {
    29. "field": "salary"
    30. }
    31. }
    32. }
    33. }
    34. }
    35. }

    查询结果:

    1. {
    2. "took" : 8,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 5,
    6. "successful" : 5,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : 5,
    12. "max_score" : 0.0,
    13. "hits" : [ ]
    14. },
    15. "aggregations" : {
    16. "age_agg" : {
    17. "doc_count_error_upper_bound" : 0,
    18. "sum_other_doc_count" : 0,
    19. "buckets" : [
    20. {
    21. "key" : 29,
    22. "doc_count" : 2,
    23. "sex_agg" : {
    24. "doc_count_error_upper_bound" : 0,
    25. "sum_other_doc_count" : 0,
    26. "buckets" : [
    27. {
    28. "key" : "女",
    29. "doc_count" : 1,
    30. "salary_avg" : {
    31. "value" : 3000.0
    32. }
    33. },
    34. {
    35. "key" : "男",
    36. "doc_count" : 1,
    37. "salary_avg" : {
    38. "value" : 6000.0
    39. }
    40. }
    41. ]
    42. },
    43. "salary_avg" : {
    44. "value" : 4500.0
    45. }
    46. },
    47. {
    48. "key" : 26,
    49. "doc_count" : 1,
    50. "sex_agg" : {
    51. "doc_count_error_upper_bound" : 0,
    52. "sum_other_doc_count" : 0,
    53. "buckets" : [
    54. {
    55. "key" : "女",
    56. "doc_count" : 1,
    57. "salary_avg" : {
    58. "value" : 9000.0
    59. }
    60. }
    61. ]
    62. },
    63. "salary_avg" : {
    64. "value" : 9000.0
    65. }
    66. },
    67. {
    68. "key" : 31,
    69. "doc_count" : 1,
    70. "sex_agg" : {
    71. "doc_count_error_upper_bound" : 0,
    72. "sum_other_doc_count" : 0,
    73. "buckets" : [
    74. {
    75. "key" : "男",
    76. "doc_count" : 1,
    77. "salary_avg" : {
    78. "value" : 4800.0
    79. }
    80. }
    81. ]
    82. },
    83. "salary_avg" : {
    84. "value" : 4800.0
    85. }
    86. }
    87. ]
    88. }
    89. }
    90. }

    9、queryString查询

            会对查询条件进行分词, 然后将分词后的查询条件和词条进行等值匹配,默认取并集(OR),可以指定单个字段也可多个查询字段。

    示例:

    1. #查询1: 查询name 中包含指定 内容分词后的数据
    2. POST /user/_search
    3. {
    4. "query": {
    5. "query_string": {
    6. "default_field": "name",
    7. "query": "张三 OR 李四"
    8. }
    9. },
    10. "size": 100
    11. }
    12. # 查询2:查询name、address 中包含指定 内容分词后的数据
    13. GET /user/_search
    14. {
    15. "query": {
    16. "query_string": {
    17. "fields": ["name","address"],
    18. "query": "张三三 or 国中人"
    19. }
    20. }
    21. }

    查询结果:

    1. #查询1:结果
    2. {
    3. "took" : 7,
    4. "timed_out" : false,
    5. "_shards" : {
    6. "total" : 5,
    7. "successful" : 5,
    8. "skipped" : 0,
    9. "failed" : 0
    10. },
    11. "hits" : {
    12. "total" : 3,
    13. "max_score" : 1.3862944,
    14. "hits" : [
    15. {
    16. "_index" : "user",
    17. "_type" : "_doc",
    18. "_id" : "2004",
    19. "_score" : 1.3862944,
    20. "_source" : {
    21. "name" : "李四",
    22. "address" : "广东省广州市花都区",
    23. "remark" : "公司底层码农员工",
    24. "age" : 26,
    25. "salary" : 9000,
    26. "birthDate" : "1993-08-18",
    27. "sex" : "女"
    28. }
    29. },
    30. {
    31. "_index" : "user",
    32. "_type" : "_doc",
    33. "_id" : "XkQdS4MByEXWPCdI40rO",
    34. "_score" : 0.68324494,
    35. "_source" : {
    36. "name" : "张三三",
    37. "age" : 29,
    38. "salary" : 3000,
    39. "address" : "北京市",
    40. "remark" : "来自中国北京市的张先生",
    41. "birthDate" : "1990-09-10",
    42. "sex" : "女"
    43. }
    44. },
    45. {
    46. "_index" : "user",
    47. "_type" : "_doc",
    48. "_id" : "13",
    49. "_score" : 0.5753642,
    50. "_source" : {
    51. "name" : "张三",
    52. "age" : 29,
    53. "salary" : 6000,
    54. "address" : "北京市",
    55. "remark" : "来自中国北京市的张先生",
    56. "birthDate" : "1990-09-10",
    57. "sex" : "男"
    58. }
    59. }
    60. ]
    61. }
    62. }
    63. # 查询2:结果
    64. {
    65. "took" : 1,
    66. "timed_out" : false,
    67. "_shards" : {
    68. "total" : 5,
    69. "successful" : 5,
    70. "skipped" : 0,
    71. "failed" : 0
    72. },
    73. "hits" : {
    74. "total" : 2,
    75. "max_score" : 1.0788078,
    76. "hits" : [
    77. {
    78. "_index" : "user",
    79. "_type" : "_doc",
    80. "_id" : "XkQdS4MByEXWPCdI40rO",
    81. "_score" : 1.0788078,
    82. "_source" : {
    83. "name" : "张三三",
    84. "age" : 29,
    85. "salary" : 3000,
    86. "address" : "北京市",
    87. "remark" : "来自中国北京市的张先生",
    88. "birthDate" : "1990-09-10",
    89. "sex" : "女"
    90. }
    91. },
    92. {
    93. "_index" : "user",
    94. "_type" : "_doc",
    95. "_id" : "13",
    96. "_score" : 0.8630463,
    97. "_source" : {
    98. "name" : "张三",
    99. "age" : 29,
    100. "salary" : 6000,
    101. "address" : "北京市",
    102. "remark" : "来自中国北京市的张先生",
    103. "birthDate" : "1990-09-10",
    104. "sex" : "男"
    105. }
    106. }
    107. ]
    108. }
    109. }

    10、重建索引

            随着业务需求的变更,索引的结构可能发生改变。ElasticSearch的索引一旦创建,只允许添加字段,不允许改变字段。因为改变字段,需要重建倒排索引,影响内部缓存结构,性能太低。那么此时,就需要重建一个新的索引,并将原有索引的数据导入到新索引中。

    1. 原索引库 :test_index_v1
    2. 新索引库 :test_index_v2

    10.1、创建test_index_v1索引、添加数据

            创建test_index_v1索引,索引名称必须全部小写。

    1. # 新建test_index_v1索引,索引名称必须全部小写
    2. PUT test_index_v1
    3. {
    4. "mappings": {
    5. "properties": {
    6. "birthday":{
    7. "type": "date"
    8. }
    9. }
    10. }
    11. }
    12. # 查询索引
    13. GET test_index_v1
    14. # 添加数据
    15. PUT test_index_v1/_doc/1
    16. {
    17. "birthday":"2020-11-11"
    18. }

    10.2、业务变更,字段类型需要变动

    1. # 查询数据
    2. GET test_index_v1/_search
    3. # 随着业务的变更,换种数据类型进行添加数据,程序会直接报错
    4. PUT test_index_v1/_doc/1
    5. {
    6. "birthday":"2020年11月11号"
    7. }

    10.3、 新建索引库 :test_index_v2

    1. # 业务变更,需要改变birthday数据类型为text
    2. # 1:创建新的索引 test_index_v2
    3. # 2:将test_index_v1 数据拷贝到 test_index_v2
    4. # 创建新的索引
    5. PUT test_index_v2
    6. {
    7. "mappings": {
    8. "properties": {
    9. "birthday":{
    10. "type": "text"
    11. }
    12. }
    13. }
    14. }

    10.4、将test_index_v1 数据拷贝到 test_index_v2

    1. # 将test_index_v1 数据拷贝到 test_index_v2
    2. POST _reindex
    3. {
    4. "source": {
    5. "index": "test_index_v1"
    6. },
    7. "dest": {
    8. "index": "test_index_v2"
    9. }
    10. }
    11. # 查询新索引库数据
    12. GET test_index_v2/_search
    13. # 在新的索引库里面添加数据
    14. PUT test_index_v2/_doc/2
    15. {
    16. "birthday":"2020年11月13号"
    17. }
    18. DELETE test_index_v1

    11、别名的使用

    11.1、查询别名

    1. #获取指定索引的别名
    2. GET /user/_alias
    3. #获取ES中所有索引的别名
    4. GET /_alias

    查询结果:

    1. # 索引user的别名查询结果:
    2. {
    3. "user" : {
    4. "aliases" : { }
    5. }
    6. }

    11.2、新增别名

    1. # 给索引user 添加別名:user_alias_1.0
    2. POST /_aliases
    3. {
    4. "actions": [
    5. {
    6. "add": {
    7. "index": "user",
    8. "alias": "user_alias_1.0"
    9. }
    10. }
    11. ]
    12. }

    别名查询结果:

    1. # 索引user的别名查询结果:
    2. {
    3. "user" : {
    4. "aliases" : {
    5. "user_alias_1.0" : { }
    6. }
    7. }
    8. }

    11.3、删除别名

    1. # 删除别名
    2. #方式一
    3. POST /_aliases
    4. {
    5. "actions": [
    6. {
    7. "remove": {
    8. "index": "user",
    9. "alias": "user_alias_1.0"
    10. }
    11. }
    12. ]
    13. }
    14. #方式二
    15. DELETE /user/_alias/user_alias_1.0

    11.4、重命名别名

    1. # 重命名别名
    2. POST /_aliases
    3. {
    4. "actions": [
    5. {
    6. "remove": {
    7. "index": "user",
    8. "alias": "user_alias_1.0"
    9. }
    10. },
    11. {
    12. "add": {
    13. "index": "user",
    14. "alias": "user_alias_2.0"
    15. }
    16. }
    17. ]
    18. }

    11.5、为多个索引指定一个别名

    1. # 为多个索引指定一个别名
    2. POST /_aliases
    3. {
    4. "actions": [
    5. {
    6. "add": {
    7. "index": "test_index_v2",
    8. "alias": "test_alias_2.0"
    9. }
    10. },{
    11. "add": {
    12. "index": "test_index_v1",
    13. "alias": "test_alias_2.0"
    14. }
    15. }
    16. ]
    17. }

    查询所有别名:

    11.6、为同个索引指定多个别名 

    1. # 为同个索引指定多个别名 
    2. POST /_aliases
    3. {
    4. "actions": [
    5. {
    6. "add": {
    7. "index": "user",
    8. "alias": "user_alias_2.0"
    9. }
    10. },{
    11. "add": {
    12. "index": "user",
    13. "alias": "user_alias_3.0"
    14. }
    15. }
    16. ]
    17. }

    11.7、通过别名读索引

    GET user_alias_2.0/_doc/13

     11.8、通过别名写索引

    1. #通过别名写索引
    2. POST /user_alias_2.0/_doc/14
    3. {
    4. "name": "Tom",
    5. "age": "26"
    6. }

  • 相关阅读:
    Collections unmodifiableCollection,emptyList,singletonList 介绍以及总结
    探究并发和并行、同步和异步、进程和线程、阻塞和非阻塞、响应和吞吐等
    TI/德州仪器 TPS2051CDBVR 功率电子开关
    spark临时文件较大问题处理
    计算机网络入门基础篇——运输层
    java中的泛型
    快速修改ppt | 显得不单调
    STM32:GPIO模拟SPI驱动ADS8361
    【单元测试】Junit 4(三)--Junit4断言
    宇宙的尽头是编制?七成毕业生进体制,清北2021届学子就业报告出炉
  • 原文地址:https://blog.csdn.net/weixin_40482816/article/details/126892859