【SpringBoot高级篇】SpringBoot集成Elasticsearch搜索引擎

1. 什么是Elasticsearch?

Elasticsearch是一个开源的分布式、RESTful 风格的搜索和数据分析引擎,它的底层是开源库Apache Lucene

Lucene可以说是当下最先进、高性能、全功能的搜索引擎库——无论是开源还是私有,但它也仅仅只是一个库。为了充分发挥其功能,你需要使用 Java 并将 Lucene 直接集成到应用程序中。 更糟糕的是,您可能需要获得信息检索学位才能了解其工作原理,因为Lucene 非常复杂。

为了解决Lucene使用时的繁复性,于是Elasticsearch便应运而生。它使用 Java 编写,内部采用 Lucene 做索引与搜索,但是它的目标是使全文检索变得更简单,简单来说,就是对Lucene 做了一层封装,它提供了一套简单一致的 RESTful API 来帮助我们实现存储和检索。

当然,Elasticsearch 不仅仅是 Lucene,并且也不仅仅只是一个全文搜索引擎。 它可以被下面这样准确地形容:

  • 一个分布式的实时文档存储,每个字段可以被索引与搜索;
  • 一个分布式实时分析搜索引擎;
  • 能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据。

由于Elasticsearch的功能强大和使用简单,维基百科、卫报、Stack Overflow、GitHub等都纷纷采用它来做搜索。现在,Elasticsearch已成为全文搜索领域的主流软件之一。

2. 安装并运行Elasticsearch

2.1 拉取镜像

docker pull elastics

2.2 启动镜像

docker run -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d -p 9200:9200 -p 9300:9300 --name ES01 elasticsearch

9300与9200区别
9300端口: ES节点之间通讯使用
9200端口: ES节点 和 外部 通讯使用

9300是TCP协议端口号,ES集群之间通讯端口号
9200端口号,暴露ES RESTful接口端口号

注意: 若是开发环境最好给他分配内存,因为,ES默认启动占用内存是2g,反正我是舍不得。

在浏览器中输入网址“http://ip:9200/”,如果看到以下信息就说明你的电脑已成功安装Elasticsearch:

3. 安装kibana

Kibana 是一个开源的分析和可视化平台,旨在与 Elasticsearch 合作。Kibana 提供搜索、查看和与存储在 Elasticsearch 索引中的数据进行交互的功能。开发者或运维人员可以轻松地执行高级数据分析,并在各种图表、表格和地图中可视化数据。

3.1 拉取kibana镜像

docker pull kibana:7.6.1

注: 版本对应

3.2 启动kibana镜像

安装完成以后需要启动kibana容器,使用--link连接到elasticsearch容器,命令如下:

docker run --name kibana --link=elasticsearch:test  -p 5601:5601 -d kibana:7.6.1

启动以后可以打开浏览器输入http://ip:5601就可以打开kibana的界面了。

  • Discover:日志管理视图 主要进行搜索和查询
  • Visualize:统计视图 构建可视化的图表
  • Dashboard:仪表视图 将构建的图表组合形成图表盘
  • Timelion:时间轴视图 随着时间流逝的数据
  • APM:性能管理视图 应用程序的性能管理系统
  • Canvas:大屏展示图
  • Dev Tools: 开发者命令视图 开发工具
  • Monitoring:健康视图 请求访问性能预警
  • Management:管理视图 管理工具

4. Elasticsearch基本概念

索引(Index)

Elasticsearch 数据管理的顶层单位就叫做 Index(索引),相当于关系型数据库里的数据库的概念。另外,每个Index的名字必须是小写。

文档(Document)

Index里面单条的记录称为 Document(文档)。许多条 Document 构成了一个 Index。Document 使用 JSON 格式表示。同一个 Index 里面的 Document,不要求有相同的结构(scheme),但是最好保持相同,这样有利于提高搜索效率。

类型(Type)

Document 可以分组,比如employee这个 Index 里面,可以按部门分组,也可以按职级分组。这种分组就叫做 Type,它是虚拟的逻辑分组,用来过滤 Document,类似关系型数据库中的数据表。

不同的 Type 应该有相似的结构(Schema),性质完全不同的数据(比如 products 和 logs)应该存成两个 Index,而不是一个 Index 里面的两个 Type(虽然可以做到)。

文档元数据(Document metadata)

文档元数据为_index, _type, _id, 这三者可以唯一表示一个文档,_index表示文档在哪存放,_type表示文档的对象类别,_id为文档的唯一标识。

字段(Fields)

每个Document都类似一个JSON结构,它包含了许多字段,每个字段都有其对应的值,多个字段组成了一个 Document,可以类比关系型数据库数据表中的字段。

4.1 全文搜索(Full-text Search)

全文检索是指计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。在全文搜索的世界中,存在着几个庞大的帝国,也就是主流工具,主要有:

  • Apache Lucene
  • Elasticsearch
  • Solr
  • Ferret

倒排索引(Inverted Index)

该索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted index)。Elasticsearch能够实现快速、高效的搜索功能,正是基于倒排索引原理。

节点 & 集群(Node & Cluster)

Elasticsearch 本质上是一个分布式数据库,允许多台服务器协同工作,每台服务器可以运行多个Elasticsearch实例。单个Elasticsearch实例称为一个节点(Node),一组节点构成一个集群(Cluster)

在 Elasticsearch 中,文档(Document)归属于一种类型(Type),而这些类型存在于索引(Index)中,下图展示了Elasticsearch与传统关系型数据库的类比:

Relational DBElasticsearch
数据库(database)索引(indices)
表(tables)types
行(rows)documents
字段(columns)fifields

5. Elasticsearch入门

Elasticsearch提供了多种交互使用方式,包括Java APIRESTful API 。所有其他语言可以使用RESTful API 通过端口 9200 和 Elasticsearch 进行通信,你可以用你最喜爱的 web 客户端访问 Elasticsearch 。甚至,你还可以使用 curl 命令来和 Elasticsearch 交互。

一个Elasticsearch请求和任何 HTTP 请求一样,都由若干相同的部件组成:

curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'

返回的数据格式为JSON,因为Elasticsearch中的文档以JSON格式储存。其中,被 < > 标记的部件:

部件说明
VERB适当的 HTTP 方法 或 谓词 : GET、 POST、 PUT、 HEAD 或者 DELETE。
PROTOCOLhttp 或者 https(如果你在 Elasticsearch 前面有一个 https 代理)
HOSTElasticsearch 集群中任意节点的主机名,或者用 localhost 代表本地机器上的节点。
PORT运行 Elasticsearch HTTP 服务的端口号,默认是 9200 。
PATHAPI 的终端路径(例如 _count 将返回集群中文档数量)。Path 可能包含多个组件,例如:_cluster/stats 和 _nodes/stats/jvm 。
QUERY_STRING任意可选的查询字符串参数 (例如 ?pretty 将格式化地输出 JSON 返回值,使其更容易阅读)
BODY一个 JSON 格式的请求体 (如果请求需要的话)

对于HTTP方法,它们的具体作用为:

methodurl地址url地址描述
GETlocalhost:9200/索引名称/类型名称/文档id查询文档通过文档id
POSTlocalhost:9200/索引名称/类型名称创建文档(随机文档id)
PUTlocalhost:9200/索引名称/类型名称/文档id创建文档(指定文档id)
DELETElocalhost:9200/索引名称/类型名称/文档id删除文档
HEAD请求获取对象的基础信息
POSTlocalhost:9200/索引名称/类型名称/文档id/_update修改文档
POSTlocalhost:9200/索引名称/类型名称/_search查询所有数据

Elasticsearch是把restful玩到了极限

我们以下面的数据为例,来展示Elasticsearch的用法。 以下全部的操作都在Kibana中完成,创建的indexconference, typeevent

5.1 插入数据

首先创建index为conference, 创建type为event, 插入id为1的第一条数据,

PUT /conference/event/1
{
  "host": "Dave Nolan",
  "title": "real-time Elasticsearch",
  "description": "we will discuss using Elasticsratch to index data in real time",
  "attendees": ["Dave", "Shay", "John", "Harry"],
  "date": "2013-02-18T18:30",
  "reviews": 3
}
PUT /conference/event/2
{
  "host": "Andy",
  "title": "Moving Hadoop to the mainstream",
  "description": "Come hear about how Hadoop is moving to the main stram",
  "attendees": ["Andy", "Matt", "Bill", "Clint"],
  "date": "2013-07-24T18:30",
  "reviews": 1
}
PUT /conference/event/3
{
  "host": "Andy",
  "title": "Big Data and the cloud at Microsoft",
  "description": "Disussion abour the Microsoft  Azure cloud and HDInsight",
  "attendees": ["Andy", "Michael", "Ben", "David"],
  "date": "2013-07-31T18:30",
  "reviews": 1
}

PUT /conference/event/4
{
  "host": "Mik",
  "title": "Logging and Elasticsearch",
  "description": "Get a deep dive for what Elastisearch is and how it can be used for logging with Logstash as well as Kibaana",
  "attendees": ["Shay", "Rashid", "Erik", "Grant"],
  "date": "2013-04-24T18:30",
  "reviews": 3
}

PUT /conference/event/5
{
  "host": "Dave",
  "title": "Elasticsearch at Rangespan and Exonar",
  "description": "Representatives from Rangespan and Exonar will come and discuss how they use Elasticsearch",
  "attendees": ["Dave", "Andrew", "David", "Clint"],
  "date": "2013-06-24T18:30",
  "reviews": 3
}

在上面的命令中,路径/conference/event/1表示文档的indexconference,typeevent, id为1. 类似于上面的操作,依次插入剩余的4条数据,完成插入

5.2 删除数据

比如我们想要删除conferenceevent里面id为5的数据,只需运行下面命令即可:

DELETE /conference/event/5

返回结果如下:

{
  "_index" : "conference",
  "_type" : "event",
  "_id" : "5",
  "_version" : 2,
  "result" : "deleted",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}

表示该文档已成功删除。如果想删除整个event类型,可输入命令:

DELETE /conference/event

如果想删除整个conference索引,可输入命令:

DELETE /conference

5.3 修改数据

修改数据的命令为POST, 比如我们想要将conferenceevent里面id4的文档的作者改为Bob,那么需要运行命令如下:

POST /conference/event/4/_update
{
  "doc": {"host": "xiaoming"}
}

返回的信息如下:(表示修改数据成功)

{
  "_index" : "conference",
  "_type" : "event",
  "_id" : "4",
  "_version" : 3,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 10,
  "_primary_term" : 1
}

5.4 Elasticsearch 六种搜索方式

  • query string search
  • query DSL
  • query filter
  • full-text search
  • phrase search
  • highlight search

查询结果解释

  • took - 耗费多少毫秒
  • time_out - 是否超时
  • _shards - 数据分片情况
  • hits.total - 查询结果的数量
  • hits.max_score - document 对于一个 search 的相关度匹配分数,越相关分数越高
  • hits.hits - 匹配 document 的详细数据
5.4.1 query string search

语法

GET /conference/event/_search
搜索全部
GET /conference/event/_search
条件查询排序

搜索attendees包含Dave的名字,而且按照reviews降序排序:

GET /conference/event/_search?q=attendees:Dave&sort=reviews:desc

结果:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [
      {
        "_index" : "conference",
        "_type" : "event",
        "_id" : "3",
        "_score" : null,
        "_source" : {
          "host" : "Andy",
          "title" : "Elasticsearch at Rangespan and Exonar",
          "description" : "Representatives from Rangespan and Exonar will come and discuss how they use Elasticsearch",
          "attendees" : [
            "Dave",
            "Andrew",
            "David",
            "Clint"
          ],
          "date" : "2013-06-24T18:30",
          "reviews" : 3
        },
        "sort" : [
          3
        ]
      },
      {
        "_index" : "conference",
        "_type" : "event",
        "_id" : "2",
        "_score" : null,
        "_source" : {
          "host" : "Dave Nolan",
          "title" : "Elasticsearch at Rangespan and Exonar",
          "description" : "Representatives from Rangespan and Exonar will come and discuss how they use Elasticsearch",
          "attendees" : [
            "Dave",
            "Andrew",
            "David",
            "Clint"
          ],
          "date" : "2013-06-24T18:30",
          "reviews" : 2
        },
        "sort" : [
          2
        ]
      },
      {
        "_index" : "conference",
        "_type" : "event",
        "_id" : "1",
        "_score" : null,
        "_source" : {
          "host" : "Dave",
          "title" : "Elasticsearch at Rangespan and Exonar",
          "description" : "Representatives from Rangespan and Exonar will come and discuss how they use Elasticsearch",
          "attendees" : [
            "Dave",
            "Andrew",
            "David",
            "Clint"
          ],
          "date" : "2013-06-24T18:30",
          "reviews" : 1
        },
        "sort" : [
          1
        ]
      }
    ]
  }
}

适用于临时的在命令行使用一些工具,比如curl,快速的发出请求,来检索想要的信息;但是如果查询请求很复杂,是很难去构建的,在生产环境中,几乎很少使用query string search

属性包含关键字查询
GET /conference/event/_search?q=attendees:Dave

GET /conference/event/_search?q=+attendees:Dave
属性attendees包含Dave

GET /conference/event/_search?q=-attendees:Dave
属性attendees不包含Dave

GET /conference/event/_search?q=attendees:Dave&sort=reviews:desc
查询attendees包含Dave,同时按照reviews降序排序
  • +是必须包含
  • -是不包含
属性中关键字搜索
GET  /conference/event/_search?q=Dave
直接可以搜索所有的field,任意一个field包含指定的关键字就可以搜索出来。
5.4.2 query DSL

DSL:Domain Specified Language,特定领域的语言

http request body:请求体,可以用json的格式来构建查询语法,比较方便,可以构建各种复杂的语法,比query string search肯定强大多了

查询所有
GET  /conference/event/_search
{
  "query": { "match_all": {} }
}
条件查询排序

查询attendees包含Dave,同时按照reviews降序排序

GET  /conference/event/_search
{
  "query": { 
    "match": {
      "attendees":"Dave"
    } 
  },
  "sort": [
    {
      "reviews": {
        "order": "desc"
      }
    }
  ]
}
分页查询
  • from: 从第几条开始查
  • size: 查多少条

查询所有,在分页

GET /conference/event/_search
{
  "query": {
   "match_all": {}
  },
  "from": 2,
  "size": 3
}

查询字段attendees包含Dave关键字,在分页

GET /conference/event/_search
{
  "query": {
    "match": {
      "attendees": "Dave"
    }
  },
  "from": 2,
  "size": 3
}
查询指定属性
GET  /conference/event/_search

{
  "query": { "match_all": {} },
  "_source": ["attendees", "host"]
}
5.4.2 query filter(范围查询)

搜索attendees属性包含 Clint ,而且reviews大于等于2

GET /conference/event/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "attendees": "Clint"
          }
        }
      ],
      "filter": {
        "range": {
          "reviews": {
            "gte": 2
      
          }
        }
      }
    }
  }
}
  • gt : 大于
  • lt : 小于
  • eq : 等于
  • ne : 不等于
  • gte : 大于等于
  • lte : 小于等于
5.4.2 full-text search

全文检索 - 会将输入的关键字拆解,去倒排索引里面一一匹配,只要匹配上任意一个拆解后的单词,就可以作为结果返回 ,返回的结果包含了两个文档,放在数组 hits 中。让我们对这个结果做一些分析,第一个文档的description里面含有“using Elasticsearch”,这个能匹配“use Elasticsearch”是因为Elasticsearch含有内置的词干提取算法,之后两个文档按_score进行排序,_score字段表示文档的相似度(默认的相似度算法为BM25)。

GET /conference/event/_search
{
  "query": {
    "match": {
      "description": "and Elasticsearch"
    }
  }
}

结果

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 1.1001158,
    "hits" : [
      {
        "_index" : "conference",
        "_type" : "event",
        "_id" : "4",
        "_score" : 1.1001158,
        "_source" : {
          "host" : "xiaoming",
          "title" : "Elasticsearch at Rangespan and Exonar",
          "description" : "how they use Elasticsearch",
          "attendees" : [
            "Andy",
            "Michael",
            "Ben",
            "David"
          ],
          "date" : "2013-06-24T18:30",
          "reviews" : 4
        }
      },
      {
        "_index" : "conference",
        "_type" : "event",
        "_id" : "3",
        "_score" : 0.822573,
        "_source" : {
          "host" : "Andy",
          "title" : "Elasticsearch at Rangespan and Exonar",
          "description" : "and discuss",
          "attendees" : [
            "Dave",
            "Andrew",
            "David",
            "Clint"
          ],
          "date" : "2013-06-24T18:30",
          "reviews" : 3
        }
      },
      {
        "_index" : "conference",
        "_type" : "event",
        "_id" : "2",
        "_score" : 0.6333549,
        "_source" : {
          "host" : "Dave Nolan",
          "title" : "Elasticsearch at Rangespan and Exonar",
          "description" : "and Exonar will come",
          "attendees" : [
            "Dave",
            "Andrew",
            "David",
            "Clint"
          ],
          "date" : "2013-06-24T18:30",
          "reviews" : 2
        }
      }
    ]
  }
}

当 and Elasticsearch 作为查询条件时会被拆分成 and、Elasticsearch 两个查询条件,但是查询结果的 _score 会体现跟原始查询条件的匹配度

5.4.2 phrase search(短语搜索)

短语搜索 - 跟全文检索相反,搜索关键字必须在指定的字段文本中完全匹配

GET /conference/event/_search
{
  "query": {
    "match_phrase": {
      "description": "Elasticsearch"
    }
  }
}
highlight search

高亮搜索 - 被匹配的关键字将会在查询结果中高亮标注(默认*)*

GET /conference/event/_search {   "query": {     "match": {       "description": "and"     }   },   "highlight": {     "fields": {       "description":{}     }   } }

6. SpringBoot2.2.2整合ElasticSearch7.6.1

Elasticsearch Java API有四类client连接方式

  • TransportClient
  • RestClient
  • Jest
  • Spring Data Elasticsearch

其中TransportClientRestClientElasticsearch原生的api。TransportClient可以支持2.x,5.x版本,TransportClient将会在Elasticsearch 7.0弃用并在8.0中完成删除,替而代之,我们使用JavaHigh LevelRESTClient,它使用HTTP请求而不是Java序列化请求。JestJava社区开发的,是Elasticsearch的Java Http Rest客户端;Spring Data Elasticsearch是spring集成的Elasticsearch开发包。

TransportClient将会在后面的版本中弃用,因此不推荐后续使用;而Jest由于是社区维护,所以更新有一定延迟,目前最新版对接ES6.3.1,近一个月只有四个issue,说明整体活跃度较低,因此也不推荐使用;Spring Data Elasticsearch主要是与Spring生态对接,可以在web系统中整合到Spring中使用。目前比较推荐使用官方的高阶、低阶RestClient,官方维护,比较值得信赖。主要说rest高级客户端连接,也是官网推荐的连接方式

restHighLevelClient

Pom

引入模块需要的依赖

<!--SpringBoot默认使用SpringData ElasticSearch模块进行操作-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.41</version>
        </dependency>

        <!--jest连接方式  start-->
        <dependency>
            <groupId>io.searchbox</groupId>
            <artifactId>jest</artifactId>
            <version>6.3.1</version>
        </dependency>

        <!--jest  end-->

yml

rest连接客户端

spring:
  elasticsearch:
    rest:
      uris: http://172.16.0.192:9200

config

添加我们的rest高级客户端连接地址

public class ElasticSearchConfig {
    @Bean
    public RestHighLevelClient restHighLevelClient() {
        RestHighLevelClient restClient = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("172.16.0.192", 9200, "http")));
        return restClient;
    }
}

entity

@Data
@NoArgsConstructor
@AllArgsConstructor
@Component
public class User {
    private String name;
    private Integer age;
}

测试

索引的创建
    @Autowired
    RestHighLevelClient restHighLevelClient;

    //索引的创建
    @Test
    void testCreateIndex() throws IOException {
        // 1.创建索引请求
        CreateIndexRequest request = new CreateIndexRequest(ESconst.ES_INDEX);
        //2.客户端执行请求
        CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
        System.out.println(createIndexResponse);
    }
获取索引
 //获取索引
 @Test
 void testExistIndex() throws IOException {
     GetIndexRequest request = new GetIndexRequest(ESconst.ES_INDEX);
     boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
     System.out.println(exists);
 }
删除索引
//删除索引
@Test
void testDeleteIndex() throws IOException {
    DeleteIndexRequest request = new DeleteIndexRequest(ESconst.ES_INDEX);
    //删除
    AcknowledgedResponse delete = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
    System.out.println(delete.isAcknowledged());
}
添加文档
// 测试添加文档
    @Test
    void testAddDocument() throws IOException {
        User user = new User("三月三", 19);
        //创建请求
        IndexRequest request = new IndexRequest(ESconst.ES_INDEX);
        //规则 put /index/_doc/1
        request.id("2");
        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");

        //将我们的数据放入请求
        request.source(JSON.toJSONString(user), XContentType.JSON);
        //客户端发送请求,获取响应结果
        IndexResponse indexResponse = restHighLevelClient.index(request, RequestOptions.DEFAULT);
        System.out.println(indexResponse.toString());
        //对应我们命令返回的状态
        System.out.println(indexResponse.status());

    }
获取文档
 // 获取文档,判断是否存在 get /index/doc/1
    @Test
    void testIsExist() throws IOException {
        GetRequest request = new GetRequest(ESconst.ES_INDEX, "1");
        // 不获取返回的 _source 的上下文了
        request.fetchSourceContext(new FetchSourceContext(false));
        request.storedFields("_none_");
        boolean exists = restHighLevelClient.exists(request, RequestOptions.DEFAULT);
        System.out.println(exists);
    }
获取文档信息
   //获取文档信息
    @Test
    void testGetDocument() throws IOException {
        GetRequest getRequest = new GetRequest(ESconst.ES_INDEX, "1");
        GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
        System.out.println(getResponse.getSourceAsString());
        System.out.println(getResponse);
    }
更新文档的信息
   //更新文档的信息
    @Test
    void testUpdateDocument() throws IOException {
        UpdateRequest request = new UpdateRequest(ESconst.ES_INDEX, "1");
        request.timeout("1s");
        User user = new User("狂神说java", 18);
        request.doc(JSON.toJSONString(user), XContentType.JSON);
        UpdateResponse updateResponse = restHighLevelClient.update(request, RequestOptions.DEFAULT);
        System.out.println(updateResponse.status());

    }
删除文档的信息
  //删除文档的信息
    @Test
    void testDeleteRequest() throws IOException {
        DeleteRequest request = new DeleteRequest(ESconst.ES_INDEX, "1");
        request.timeout("1s");

        DeleteResponse response = restHighLevelClient.delete(request, RequestOptions.DEFAULT);
        System.out.println(response.status());
    }
批量插入数据
    // 特殊的,真的项目一般都会批量插入数据!
    @Test
    void testBulkRequest() throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("10s");
        ArrayList<User> userList = new ArrayList<>();
        userList.add(new User("zysheep1", 1));
        userList.add(new User("zysheep2", 2));
        userList.add(new User("zysheep3", 3));
        userList.add(new User("zysheep4", 5));
        userList.add(new User("zysheep5", 6));
        userList.add(new User("zysheep7", 7));
        for (int i = 0; i < userList.size(); i++) {
            //批量跟新删除
            bulkRequest.add(
                    new IndexRequest(ESconst.ES_INDEX)
                            .id("" + (i + 1)).source(JSON.toJSONString(userList.get(i)), XContentType.JSON));
        }
        BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        System.out.println(bulkResponse.hasFailures());
    }
查询
 /**
     * 查询
     * SearchRequest 搜索请求
     * SearchSourceBuilder 条件构造
     * HighlightBuilder 构建高亮
     * TermQueryBuilder 精确查询
     * MatchAllQueryBuilder匹配所有
     * QueryBuilder 对应我们刚才看到的命令!
     * 查询条件,我们可以使用 QueryBuilders 工具来实现
     * QueryBuilders.termQuery 精确
     * QueryBuilders.matchAllQuery() 匹配所有
     */
    @Test
    void testSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest(ESconst.ES_INDEX);
        //构建搜索条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.highlighter();

        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "zysheep1");

        searchSourceBuilder.query(termQueryBuilder);
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println(JSON.toJSONString(searchResponse.getHits()));
        System.out.println("=================================");
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            System.out.println(hit.getSourceAsMap());
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李熠漾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值