第1章 Elasticsearch 概述

1.1 Elasticsearch 是什么

The Elastic Stack, 包括 Elasticsearch、Kibana、Beats 和 Logstash(也称为 ELK Stack)。 能够安全可靠地获取任何来源、任何格式的数据,然后实时地对数据进行搜索、分析和可视 化。Elaticsearch,简称为 ES,ES 是一个开源的高扩展的分布式全文搜索引擎,是整个 Elastic Stack 技术栈的核心。它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上 百台服务器,处理 PB 级别的数据。

1.2 全文搜索引擎

Google,百度类的网站搜索,它们都是根据网页中的关键字生成索引,我们在搜索的时 候输入关键字,它们会将该关键字即索引匹配到的所有网页返回;还有常见的项目中应用日 志的搜索等等。对于这些非结构化的数据文本,关系型数据库搜索不是能很好的支持。

一般传统数据库,全文检索都实现的很鸡肋,因为一般也没人用数据库存文本字段。进 行全文检索需要扫描整个表,如果数据量大的话即使对 SQL 的语法优化,也收效甚微。建 立了索引,但是维护起来也很麻烦,对于 insert 和 update 操作都会重新构建索引。

这里说到的全文搜索引擎指的是目前广泛应用的主流搜索引擎。它的工作原理是计算机 索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的 次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反 馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程

第2章 Elasticsearch 入门

2.2 Elasticsearch 基本操作

2.2.1 RESTful

REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就 是 RESTful。Web 应用程序最重要的 REST 原则是,客户端和服务器之间的交互在请求之 间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。如果服务 器在请求之间的任何时间点重启,客户端不会得到通知。此外,无状态请求可以由任何可用 服务器回答,这十分适合云计算之类的环境。客户端可以缓存数据以改进性能。

在服务器端,应用程序状态和功能可以分为各种资源。资源是一个有趣的概念实体,它 向客户端公开。资源的例子有:应用程序对象、数据库记录、算法等等。每个资源都使用 URI (Universal Resource Identifier) 得到一个唯一的地址。所有资源都共享统一的接口,以便在客 户端和服务器之间传输状态。使用的是标准的 HTTP 方法,比如 GET、PUT、POST 和 DELETE。

在 REST 样式的 Web 服务中,每个资源都有一个地址。资源本身都是方法调用的目 标,方法列表对所有资源都是一样的。这些方法都是标准方法,包括 HTTP GET、POST、 PUT、DELETE,还可能包括 HEAD 和 OPTIONS。简单的理解就是,如果想要访问互联 网上的资源,就必须向资源所在的服务器发出请求,请求体中必须包含资源的网络路径,以 及对资源进行的操作(增删改查)。

2.2.3 数据格式

Elasticsearch 是面向文档型数据库,一条数据在这里就是一个文档。为了方便大家理解, 我们将 Elasticsearch 里存储文档数据和关系型数据库 MySQL 存储数据的概念进行一个类比

ES 里的 Index 可以看做一个库,而 Types 相当于表,Documents 则相当于表的行。 这里 Types 的概念已经被逐渐弱化,Elasticsearch 6.X 中,一个 index 下已经只能包含一个 type,Elasticsearch 7.X 中, Type 的概念已经被删除了。

2.2.4 HTTP 操作
2.2.4.1 索引操作

1) 创建索引

对比关系型数据库,创建索引就等同于创建数据库

在 Postman 中,向 ES 服务器发 PUT 请求 :http://127.0.0.1:9200/shopping

请求后,服务器返回响应

{
 "acknowledged"【响应结果】: true, # true 操作成功
 "shards_acknowledged"【分片结果】: true, # 分片操作成功
 "index"【索引名称】: "shopping"
}
# 注意:创建索引库的分片数默认 1 片,在 7.0.0 之前的 Elasticsearch 版本中,默认 5 片

如果重复添加索引,会返回错误信息

2) 查看所有索引

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/_cat/indices?v

这里请求路径中的_cat 表示查看的意思,indices 表示索引,所以整体含义就是查看当前 ES 服务器中的所有索引,就好像 MySQL 中的 show tables 的感觉。

3) 查看单个索引

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/shopping

查看索引向 ES 服务器发送的请求路径和创建索引是一致的。但是 HTTP 方法不一致。这里 可以体会一下 RESTful 的意义, 请求后,服务器响应结果如下:

{ 
    "shopping"【索引名】: {         
        "aliases"【别名】: {}, 
        "mappings"【映射】: {}, 
        "settings"【设置】: { 
            "index"【设置 - 索引】: { 
                "creation_date"【设置 - 索引 - 创建时间】: "1614265373911", 
                "number_of_shards"【设置 - 索引 - 主分片数量】: "1", 
                "number_of_replicas"【设置 - 索引 - 副分片数量】: "1", 
                "uuid"【设置 - 索引 - 唯一标识】: "eI5wemRERTumxGCc1bAk2A", 
                "version"【设置 - 索引 - 版本】: { 
                    "created": "7080099" 
                }, 
                "provided_name"【设置 - 索引 - 名称】: "shopping" 
            } 
        } 
    } } 

4) 删除索引

在 Postman 中,向 ES 服务器发 DELETE 请求http://127.0.0.1:9200/shopping

2.2.4.2 文档操作

1) 创建文档

索引已经创建好了,接下来我们来创建文档,并添加数据。这里的文档可以类比为关系型数据库中的表数据,添加的数据格式为 JSON 格式

在 Postman 中,向 ES 服务器发 POST 请求 http://127.0.0.1:9200/shopping/_doc

请求体内容为:

{ 
    "title":"小米手机", 
    "category":"小米", 
    "images":"http://www.gulixueyuan.com/xm.jpg", 
    "price":3999.00 
}

此处发送请求的方式必须为 POST,不能是 PUT,否则会发生错误

服务器响应结果如下:

{ 
   "_index"【索引】: "shopping", 
    "_type"【类型-文档】: "_doc", 
    "_id"【唯一标识】: "Xhsa2ncBlvF_7lxyCE9G", #可以类比为MySQL中的主键,随机生成 
    "_version"【版本】: 1, 
    "result"【结果】: "created", #这里的create表示创建成功 
    "_shards"【分片】: { 
        "total"【分片 - 总数】: 2, 
        "successful"【分片 - 成功】: 1, 
        "failed"【分片 - 失败】: 0 
    }, 
    "_seq_no": 0, 
    "_primary_term": 1 
} 

上面的数据创建后,由于没有指定数据唯一性标识(ID),默认情况下,ES 服务器会随机生成一个。

如果想要自定义唯一性标识,需要在创建时指定:http://127.0.0.1:9200/shopping/_doc/1

此处需要注意:如果增加数据时明确数据主键,那么请求方式也可以为 PUT

2) 查看文档

查看文档时,需要指明文档的唯一性标识,类似于 MySQL 中数据的主键查询

在 Postman 中,向 ES 服务器发 GET 请求 http://127.0.0.1:9200/shopping/_doc/1

查询成功后,服务器响应结果:

{ 
    "_index"【索引】: "shopping", 
    "_type"【文档类型】: "_doc", 
    "_id": "1", 
    "_version": 2, 
    "_seq_no": 2, 
    "_primary_term": 2, 
    "found"【查询结果】: true, # true表示查找到,false表示未查找到 
    "_source"【文档源信息】: { 
        "title": "华为手机", 
        "category": "华为", 
        "images": "http://www.gulixueyuan.com/hw.jpg", 
        "price": 4999.00 
    } } 

3) 修改文档

和新增文档一样,输入相同的 URL 地址请求,如果请求体变化,会将原有的数据内容覆盖

在 Postman 中,向 ES 服务器发 POST 请求 http://127.0.0.1:9200/shopping/_doc/1

请求体内容为:

{ 
    "title":"华为手机", 
    "category":"华为", 
    "images":"http://www.gulixueyuan.com/hw.jpg", 
    "price":4999.00 
}

{ 
    "_index": "shopping", 
    "_type": "_doc", 
    "_id": "1", 
    "_version"【版本】: 2, 
    "result"【结果】: "updated", # updated表示数据被更新 
    "_shards": { 
        "total": 2, 
        "successful": 1, 
        "failed": 0 
    }, 
    "_seq_no": 2, 
    "_primary_term": 2 
} 

4 )修改字段修改数据时,也可以只修改某一给条数据的局部信息在 Postman 中,向 ES 服务器发 POST 请求 http://127.0.0.1:9200/shopping/_update/1

请求体内容为:

{  
  "doc": { 
    "price":3000.00 
}

5)删除文档

删除一个文档不会立即从磁盘上移除,它只是被标记成已删除(逻辑删除)。

在 Postman 中,向 ES 服务器发 DELETE 请求 http://127.0.0.1:9200/shopping/_doc/1

删除成功,服务器响应结果:

{ 
    "_index": "shopping", 
    "_type": "_doc", 
    "_id": "1", 
    "_version"【版本】: 4, #对数据的操作,都会更新版本 
    "result"【结果】: "deleted", # deleted表示数据被标记为删除 
    "_shards": { 
        "total": 2, 
        "successful": 1, 
        "failed": 0 
    }, 
    "_seq_no": 4, 
    "_primary_term": 2 
}

删除后再查询当前文档信息

如果删除一个并不存在的文档

{ 
    "_index": "shopping", 
    "_type": "_doc", 
    "_id": "1", 
    "_version": 1, 
    "result"【结果】: "not_found", # not_found表示未查找到 
    "_shards": { 
        "total": 2, 
        "successful": 1, 
        "failed": 0 
    }, 
    "_seq_no": 5, 
    "_primary_term": 2 
}

6) 条件删除文档

一般删除数据都是根据文档的唯一性标识进行删除,实际操作时,也可以根据条件对多条数据进行删除首先分别增加多条数据:

{ 
    "title":"小米手机", 
    "category":"小米", 
    "images":"http://www.gulixueyuan.com/xm.jpg", 
    "price":4000.00 
} 
 
{ 
    "title":"华为手机", 
    "category":"华为", 
    "images":"http://www.gulixueyuan.com/hw.jpg", 
    "price":4000.00 
}

ES 服务器发 POST 请求 http://127.0.0.1:9200/shopping/_delete_by_query 请求体内容为:

{ 
  "query":{ 
    "match":{ 
      "price":4000.00 
    } 
  } 
2.2.4.3 映射操作

有了索引库,等于有了数据库中的 database。接下来就需要建索引库(index)中的映射了,类似于 

 数据库(database)中的表结构(table)。

创建数据库表需要设置字段名称,类型,长度,约束等;索引库也一样,需要知道这个类型

下有哪些字段,每个字段有哪些约束信息,这就叫做映射(mapping)。

1) 创建映射

在 Postman 中,向 ES 服务器发 PUT 请求 http://127.0.0.1:9200/student/_mapping

请求体内容为:

{ 
  "properties": { 
    "name":{ 
      "type": "text", 
      "index": true 
    }, 
    "sex":{ 
      "type": "text", 
      "index": false 
    }, 
    "age":{ 
      "type": "long", 
      "index": false 
    } 
}

 

映射数据说明: 

  1. 字段名:任意填写,下面指定许多属性,例如:title、subtitle、images、price
  2. type:类型,Elasticsearch 中支持的数据类型非常丰富,说几个关键的:
    1. String 类型,又分两种: text:可分词 keyword:不可分词,数据会作为完整字段进行匹配
    2. Numerical:数值类型,分两类

基本数据类型:long、integer、short、byte、double、float、half_float

浮点数的高精度类型:scaled_float

                3.Date:日期类型

                4.Array:数组类型

                5.Object:对象

     3.index:是否索引,默认为 true,也就是说你不进行任何配置,所有字段都会被索引。

true:字段会被索引,则可以用来进行搜索

false:字段不会被索引,不能用来搜索

     4.store:是否将数据进行独立存储,默认为 false

原始的文本会存储在_source 里面,默认情况下其他提取出来的字段都不是独立存储

的,是从_source 里面提取出来的。当然你也可以独立的存储某个字段,只要设置

"store": true 即可,获取独立存储的字段要比从_source 中解析快得多,但是也会占用更多的空间,所以要根据实际业务需求来设置。

      5.analyzer:分词器,这里的 ik_max_word 即使用 ik 分词器,后面会有专门的章节学习

2.查看映射

 在 Postman 中,向 ES 服务器发 GET 请求 http://127.0.0.1:9200/student/_mapping

 3.索引映射关联

在 Postman 中,向 ES 服务器发 PUT 请求 :http://127.0.0.1:9200/student1

{ 
  "settings": {}, 
  "mappings": { 
   "properties": { 
  "name":{ 
    "type": "text", 
    "index": true 
     
  }, 
  "sex":{ 
    "type": "text", 
    "index": false 
  }, 
  "age":{ 
    "type": "long", 
    "index": false 
  } 
   } 
}

2.2.4.4 高级查询

Elasticsearch 提供了基于 JSON 提供完整的查询 DSL 来定义查询定义数据 :

 
# POST /student/_doc/1001 
{ 
"name":"zhangsan", 
"nickname":"zhangsan", 
    "sex":"男", 
    "age":30 
} 
# POST /student/_doc/1002 
{ 
"name":"lisi", 
"nickname":"lisi", 
    "sex":"男", 
    "age":20 
} 
# POST /student/_doc/1003 { 
"name":"wangwu", 
    "nickname":"wangwu", 
    "sex":"女", 
    "age":40 
} 
# POST /student/_doc/1004 
{ 
"name":"zhangsan1", 
"nickname":"zhangsan1", 
    "sex":"女", 
    "age":50 
} 
# POST /student/_doc/1005 
{ 
"name":"zhangsan2", 
"nickname":"zhangsan2", 
    "sex":"女", 
    "age":30 
} 

1.查询所有文档

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
  "query": { 
    "match_all": {} 
  } 
}

 "query":这里的query代表一个查询对象,里面可以有不同的查询属性

"match_all":查询类型,例如:match_all(代表查询所有), match,term , range 等等

 {查询条件}:查询条件会根据类型的不同,写法也有差异

2.匹配查询

match 匹配类型查询,会把查询条件进行分词,然后进行查询,多个词条之间是 or 的关系

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
  "query": { 
    "match": { 
        "name":"zhangsan" 
    } 
  } 
}

3.字段匹配查询

multi_match 与 match 类似,不同的是它可以在多个字段中查询。

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
  "query": { 
    "multi_match": { 
        "query": "zhangsan", 
        "fields": ["name","nickname"] 
    } 
}

4.关键字精确查询

term 查询,精确的关键词匹配查询,不对查询条件进行分词。

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
  "query": { 
    "term": { 
      "name": { 
        "value": "zhangsan" 
      } 
    } 
}

 

5.多关键字精确查询

terms 查询和 term 查询一样,但它允许你指定多值进行匹配。

如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件,类似于 mysql 的 in

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
  "query": { 
    "terms": { 
      "name": ["zhangsan","lisi"] 
    } 
  } } 

6.指定查询字段

默认情况下,Elasticsearch 在搜索的结果中,会把文档中保存在_source 的所有字段都返回。

如果我们只想获取其中的部分字段,我们可以添加_source 的过滤

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
  "_source": ["name","nickname"],   
  "query": { 
    "terms": { 
      "nickname": ["zhangsan"] 
    } 
}

7.过滤字段我们也可以通过:

includes:来指定想要显示的字段

excludes:来指定不想要显示的字段

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
  "_source": { 
    "includes": ["name","nickname"] 
  },   
  "query": { 
    "terms": { 
      "nickname": ["zhangsan"] 
    }   } 
}

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
  "_source": { 
    "excludes": ["name","nickname"] 
  },   
  "query": { 
    "terms": { 
      "nickname": ["zhangsan"] 
    } 
}
}

8.组合查询

`bool`把各种其它查询通过`must`(必须 )、`must_not`(必须不)、`should`(应该)的方式进行组合

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
  "query": { 
    "bool": { 
      "must": [ 
        { 
          "match": { 
            "name": "zhangsan" 
          } 
        } 
      ], 
      "must_not": [ 
        { 
          "match": { 
            "age": "40" 
          } 
        } 
      ], 
      "should": [ 
        { 
          "match": { 
            "sex": "男" 
          } 
        } 
      ] 
    } 
}
}

9.范围查询 range 查询找出那些落在指定区间内的数字或者时间。range 查询允许以下字符

操作符

说明

gt

大于>

gte

大于等于>=

lt

小于<

lte

小于等于<=

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
  "query": { 
    "range": { 
      "age": { 
        "gte": 30, 
        "lte": 35 
      } 
    } 
}
}

10 模糊查询

返回包含与搜索字词相似的字词的文档。

编辑距离是将一个术语转换为另一个术语所需的一个字符更改的次数。这些更改可以包括:

  1. 更改字符(box → fox)
  2. 删除字符(black → lack)
  3. 插入字符(sic → sick)
  4. 转置两个相邻字符(act → cat)

为了找到相似的术语,fuzzy 查询会在指定的编辑距离内创建一组搜索词的所有可能的变体或扩展。然后查询返回每个扩展的完全匹配。通过 fuzziness 修改编辑距离。一般使用默认值 AUTO,根据术语的长度生成编辑距离。

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
  "query": { 
    "fuzzy": { 
      "title": { 
        "value": "zhangsan" 
      }     } 

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
  "query": { 
    "fuzzy": { 
      "title": { 
        "value": "zhangsan", 
  "fuzziness": 2 
      } 
    } 
  } } 

11 单字段排序

sort 可以让我们按照不同的字段进行排序,并且通过 order 指定排序的方式。desc 降序,asc 升序。

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
  "query": { 
    "match": { 
        "name":"zhangsan" 
    } 
  }, 
  "sort": [{ 
    "age": { 
        "order":"desc" 
    } 
}

12.多字段排序

假定我们想要结合使用 age 和 _score 进行查询,并且匹配的结果首先按照年龄排序,然后按照相关性得分排序

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
  "query": { 
    "match_all": {} 
  }, 
  "sort": [ 
    { 
      "age": { 
        "order": "desc" 
      } 
    }, 
    { 
      "_score":{ 
        "order": "desc" 
      } 
    } 
  ] 
}

13 高亮查询

在进行关键字搜索时,搜索出的内容中的关键字会显示不同的颜色,称之为高亮。

Elasticsearch 可以对查询内容中的关键字部分,进行标签和样式(高亮)的设置。

在使用 match 查询的同时,加上一个 highlight 属性:

  1. pre_tags:前置标签
  2. post_tags:后置标签
  3. fields:需要高亮的字段
  4. title:这里声明 title 字段需要高亮,后面可以为这个字段设置特有配置,也可以空

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
  "query": { 
    "match": { 
      "name": "zhangsan" 
    } 
  }, 
  "highlight": { 
    "pre_tags": "<font color='red'>", 
    "post_tags": "</font>", 
    "fields": { 
      "name": {} 
    } 
}

14 分页查询

from:当前页的起始索引,默认从 0 开始。 from = (pageNum - 1) * size

size:每页显示多少条 

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
  "query": { 
    "match_all": {} 
  }, 
  "sort": [ 
    { 
      "age": { 
        "order": "desc" 
      } 
    } 
  ], 
  "from": 0, 
  "size": 2
}

15 聚合查询

聚合允许使用者对 es 文档进行统计分析,类似与关系型数据库中的 group by,当然还有很多其他的聚合,例如取最大值、平均值等等。

对某个字段取最大值 max

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
    "aggs":{ 
      "max_age":{ 
        "max":{"field":"age"} 
      }     }, 
    size":0
}

对某个字段取最小值

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
    "aggs":{ 
      "min_age":{ 
        "min":{"field":"age"} 
      }   
  }, 
    "size":0
}

对某个字段求和

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
    "aggs":{ 
      "sum_age":{ 
        "sum":{"field":"age"} 
      }     }, 
    "size":0
}

对某个字段取平均值

{ 
    "aggs":{ 
      "avg_age":{ 
        "avg":{"field":"age"} 
      }     }, 
    "size":0
}

对某个字段的值进行去重之后再取总数

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
    "aggs":{ 
      "distinct_age":{ 
        "cardinality":{"field":"age"} 
      } 
    }, 

"size":0
}

State 聚合

stats 聚合,对某个字段一次性返回 count,max,min,avg 和 sum 五个指标

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
    "aggs":{ 
      "stats_age":{ 
        "stats":{"field":"age"} 
      } 
    }, 
}

16  桶聚合查询

桶聚和相当于 sql 中的 group by 语句

terms 聚合,分组统计

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
    "aggs":{ 
      "age_groupby":{ 
        "terms":{"field":"age"} 
      }     }, 
"size":0
}

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

{ 
    "aggs":{ 
      "age_groupby":{ 
        "terms":{"field":"age"} 
      } 
    }, 
    "size":0 }  

2.2.5 Java API 操作

Elasticsearch 软件是由 Java 语言开发的,所以也可以通过 Java API 的方式对 Elasticsearch

服务进行访问

2.2.5.1 创建 Maven 项目

修改pom文件,增加Maven依赖关系

        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>7.8.0</version>
        </dependency>
        <!-- elasticsearch的客户端 -->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.8.0</version>
        </dependency>
        <!-- elasticsearch依赖2.x的log4j -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.8.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.8.2</version>
        </dependency>
2.2.5.2 客户端对象

创建 com.atguigu.es.test.Elasticsearch01_Client 类,代码中创建 Elasticsearch 客户端对象

因为早期版本的客户端对象已经不再推荐使用,且在未来版本中会被删除,所以这里我们采用高级 REST 客户端对象 。

注意:9200 端口为 Elasticsearch Web 通信端口,localhost 为启动 ES 服务的主机名

// 创建客户端对象 
RestHighLevelClient client = new RestHighLevelClient( 
  RestClient.builder(new HttpHost("localhost", 9200, "http")) 
); 
 ... 
 
// 关闭客户端连接 
client.close(); 
2.2.5.3 索引操作

ES 服务器正常启动后,可以通过 Java API 客户端对象对 ES 索引进行操作

1. 创建索引

package com.atguigu.es.test;/*
 *
 *  @author pengjx
 *
 * */

import org.apache.http.HttpHost;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;

import java.io.IOException;

public class ESTest_Index_create {

    public static void main(String[] args) throws IOException {

        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );


        CreateIndexRequest request = new CreateIndexRequest("user");
        CreateIndexResponse response = esClient.indices().create(request, RequestOptions.DEFAULT);

        boolean acknowledged = response.isAcknowledged();
        System.out.println(acknowledged);

        esClient.close();


    }
}

2. 查看索引

package com.atguigu.es.test;/*
 *
 *  @author pengjx
 *
 * */

import org.apache.http.HttpHost;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;

import java.io.IOException;

public class ESTest_Index_get {

    public static void main(String[] args) throws IOException {

        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );


        GetIndexRequest request = new GetIndexRequest("user");
        GetIndexResponse response = esClient.indices().get(request, RequestOptions.DEFAULT);

        System.out.println(response.getAliases());
        System.out.println(response.getMappings());
        System.out.println(response.getSettings());

        esClient.close();


    }
}

3.删除索引

package com.atguigu.es.test;/*
 *
 *  @author pengjx
 *
 * */

import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;

import java.io.IOException;

public class ESTest_Index_delete {

    public static void main(String[] args) throws IOException {

        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );


        DeleteIndexRequest request = new DeleteIndexRequest("user");
        AcknowledgedResponse response = esClient.indices().delete(request, RequestOptions.DEFAULT);

        System.out.println(response.isAcknowledged());

        esClient.close();


    }
}
2.2.5.4 文档操作

1. 新增文档创建数据模型

package com.atguigu.es.test;/*
 *
 *  @author pengjx
 *
 * */

import java.io.Serial;
import java.io.Serializable;

public class User implements Serializable {
    private static final long serialVersionUID=1L;

    private String name;
    private Integer age;
    private String sex;


    public User() {
    }

    public User(long serialVersionUID, String name, Integer age, String sex) {

        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public Integer getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(Integer age) {
        this.age = age;
    }

    /**
     * 获取
     * @return sex
     */
    public String getSex() {
        return sex;
    }

    /**
     * 设置
     * @param sex
     */
    public void setSex(String sex) {
        this.sex = sex;
    }


}

创建数据,添加到文档中

package com.atguigu.es.test;/*
 *
 *  @author pengjx
 *
 * */

import cn.hutool.json.JSONUtil;
import org.apache.http.HttpHost;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;

import java.io.IOException;

public class ESTest_Doc_Insert {

    public static void main(String[] args) throws IOException {

        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );

        IndexRequest request=new IndexRequest();
        request.index("user").id("1001");

        User user=new User();
        user.setName("zhangsan");
        user.setAge(20);
        user.setSex("男");

        String jsonStr = JSONUtil.toJsonStr(user);
        request.source(jsonStr, XContentType.JSON);


        IndexResponse indexResponse = esClient.index(request, RequestOptions.DEFAULT);


        System.out.println(indexResponse.getResult());

        esClient.close();


    }
}

2. 修改文档

package com.atguigu.es.test;/*
 *
 *  @author pengjx
 *
 * */

import cn.hutool.json.JSONUtil;
import org.apache.http.HttpHost;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;

import java.io.IOException;

public class ESTest_Doc_Update {

    public static void main(String[] args) throws IOException {

        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );


        UpdateRequest request=new UpdateRequest();
        request.index("user").id("1001");
        request.doc(XContentType.JSON,"sex","女");


        UpdateResponse response = esClient.update(request, RequestOptions.DEFAULT);


        System.out.println(response.getResult());

        esClient.close();


    }
}

3. 查询文档

package com.atguigu.es.test;/*
 *
 *  @author pengjx
 *
 * */

import org.apache.http.HttpHost;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;

import java.io.IOException;

public class ESTest_Doc_Get {

    public static void main(String[] args) throws IOException {

        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );

        GetRequest request = new GetRequest();
        request.index("user").id("1001");

        GetResponse response = esClient.get(request, RequestOptions.DEFAULT);

        System.out.println(response.getSourceAsString());

        esClient.close();


    }
}

删除文档

package com.atguigu.es.test;/*
 *
 *  @author pengjx
 *
 * */

import org.apache.http.HttpHost;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;

import java.io.IOException;

public class ESTest_Doc_Delete {

    public static void main(String[] args) throws IOException {

        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );

        DeleteRequest request = new DeleteRequest();
        request.index("user").id("1001");

        esClient.delete(request,RequestOptions.DEFAULT);


        esClient.close();


    }
}

批量操作

批量新增

package com.atguigu.es.test;/*
 *
 *  @author pengjx
 *
 * */

import cn.hutool.json.JSONUtil;
import org.apache.http.HttpHost;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;

import java.io.IOException;

public class ESTest_Doc_Batch_Insert {

    public static void main(String[] args) throws IOException {

        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );


        BulkRequest request=new BulkRequest();

        request.add(new IndexRequest().index("user").id("1001").source(XContentType.JSON,"name","aaa","age",30,"sex","男"));
        request.add(new IndexRequest().index("user").id("1002").source(XContentType.JSON,"name","bbb","age",30,"sex","男"));
        request.add(new IndexRequest().index("user").id("1003").source(XContentType.JSON,"name","ccc","age",30,"sex","男"));
        request.add(new IndexRequest().index("user").id("1004").source(XContentType.JSON,"name","ddd","age",30,"sex","女"));
        request.add(new IndexRequest().index("user").id("1005").source(XContentType.JSON,"name","eee","age",30,"sex","女"));
        request.add(new IndexRequest().index("user").id("1006").source(XContentType.JSON,"name","fff","age",30,"sex","女"));


        esClient.bulk(request,RequestOptions.DEFAULT);


        esClient.close();


    }
}

批量删除:

package com.atguigu.es.test;/*
 *
 *  @author pengjx
 *
 * */

import org.apache.http.HttpHost;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;

import java.io.IOException;

public class ESTest_Doc_Batch_Delete {

    public static void main(String[] args) throws IOException {

        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );


        BulkRequest request=new BulkRequest();

        request.add(new DeleteRequest().index("user").id("1001"));
        request.add(new DeleteRequest().index("user").id("1002"));
        request.add(new DeleteRequest().index("user").id("1003"));


        esClient.bulk(request,RequestOptions.DEFAULT);


        esClient.close();


    }
}
2.2.5.5 高级查询

1) 请求体查询

  • 查询所有索引数据
  SearchRequest request = new SearchRequest();
        request.indices("user");


        request.source(new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()));

        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();

        System.out.println(response.getTook());
        System.out.println(hits.getTotalHits());

        for (SearchHit hit : hits) {
            System.out.println(hit);
        }
  • term 查询,查询条件为关键字
SearchRequest request = new SearchRequest();
        request.indices("user");

        request.source(new SearchSourceBuilder().query(QueryBuilders.termQuery("name","aaa")));

        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();

        System.out.println(hits.getTotalHits());
        System.out.println(response.getTook());

        for (SearchHit hit : hits) {
            System.out.println(hit);
        }

分页查询

SearchRequest request = new SearchRequest();
        request.indices("user");

        SearchSourceBuilder query = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
        query.from(0);
        query.size(2);

        request.source(query);

        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();

        System.out.println(hits.getTotalHits());
        System.out.println(response.getTook());

        for (SearchHit hit : hits) {
            System.out.println(hit);
        }
  • 数据排序
 SearchRequest request = new SearchRequest();
        request.indices("user");

        SearchSourceBuilder query = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
        query.sort("age", SortOrder.ASC);
        request.source(query);

        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();

        System.out.println(hits.getTotalHits());
        System.out.println(response.getTook());

        for (SearchHit hit : hits) {
            System.out.println(hit);
        }
  • 过滤字段
SearchRequest request = new SearchRequest();
        request.indices("user");

        SearchSourceBuilder query = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());

        String[] includes={"name"};
        String[] excludes={};
        query.fetchSource(includes,excludes);

        request.source(query);

        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();

        System.out.println(hits.getTotalHits());
        System.out.println(response.getTook());

        for (SearchHit hit : hits) {
            System.out.println(hit);
        }
  • Bool查询
SearchRequest request = new SearchRequest();
        request.indices("user");

        SearchSourceBuilder builder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.matchQuery("name","aaa"));
        boolQueryBuilder.must(QueryBuilders.matchQuery("age",30));


        builder.query(boolQueryBuilder);

        request.source(builder);

        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();

        System.out.println(hits.getTotalHits());
        System.out.println(response.getTook());

        for (SearchHit hit : hits) {
            System.out.println(hit);
        }
  • 范围查询
SearchRequest request = new SearchRequest();
        request.indices("user");

        SearchSourceBuilder builder = new SearchSourceBuilder();
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age");

        rangeQueryBuilder.gte(30);
        rangeQueryBuilder.lte(40);

        builder.query(rangeQueryBuilder);

        request.source(builder);

        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();

        System.out.println(hits.getTotalHits());
        System.out.println(response.getTook());

        for (SearchHit hit : hits) {
            System.out.println(hit);
        }
  • 模糊查询
 SearchRequest request = new SearchRequest();
        request.indices("user");

        SearchSourceBuilder builder = new SearchSourceBuilder();
        FuzzyQueryBuilder fuzziness = QueryBuilders.fuzzyQuery("name", "aaa").fuzziness(Fuzziness.ONE);


        builder.query(fuzziness);

        request.source(builder);

        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();

        System.out.println(hits.getTotalHits());
        System.out.println(response.getTook());

        for (SearchHit hit : hits) {
            System.out.println(hit);
        }

2) 高亮查询

SearchRequest request = new SearchRequest();
        request.indices("user");

        SearchSourceBuilder builder = new SearchSourceBuilder();
        TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("name", "aaa");

        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<font color='red'>");
        highlightBuilder.postTags("</font>");
        highlightBuilder.field("name");

        builder.highlighter(highlightBuilder);
        builder.query(termsQueryBuilder);

        request.source(builder);

        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();

        System.out.println(hits.getTotalHits());
        System.out.println(response.getTook());

        for (SearchHit hit : hits) {
            System.out.println(hit);
        }

3)聚合查询

//聚合查询
        SearchRequest request = new SearchRequest();
        request.indices("user");

        SearchSourceBuilder builder = new SearchSourceBuilder();

        AggregationBuilder aggregation= AggregationBuilders.terms("maxAge").field("age");
        builder.aggregation(aggregation);

        //builder.query(termsQueryBuilder);

        request.source(builder);

        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();

        System.out.println(hits.getTotalHits());
        System.out.println(response.getTook());

        for (SearchHit hit : hits) {
            System.out.println(hit);
        }

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐