ElasticSearch入门学习教程

前言

本片博客是本人通过观看狂神说的视频记录的笔记,以此记录方便需要时查阅。
视频地址:https://www.bilibili.com/video/BV17a4y1x7zq


1.ElasticSearch的简介

ElasticSearch,简称ES。ES是一个开源的高扩展分布式全文检索引擎,它可以近乎实时的存储、检索数据;本身的扩展性很好,可以扩展到上百台服务器,处理BP(大数据)级别的数据。ES也使用Java开发并使用Lucene作为其核心来实现所有缩影和搜索功能,但是它的目的是通过简单的RESTFul API来隐藏Lucene的复杂性,从而让全文搜索变得简单。

2.ElasticSearch安装及配置

2.1.基于Docker安装ElasticSearch

# 下载7.6.1版本的ElasticSearch镜像
docker pull elasticsearch:7.6.1
# 通过ElasticSearch镜像创建并容器
# ps:9200对外访问端口,9300通信端口
docker run -d --name es -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch

2.2.配置

# 进入elasticsearch容器内部
docker exec -it es /bin/bash
# 进入config目录,找到elasticsearch.yml文件
cd config
# 编辑elasticsearch.yml文件
vi elasticsearch.yml

详细如下图:
cluster.name:自定义集群名称
network.host:当前es节点绑定的ip地址,默认127.0.0.1,如果需要开放对外访问这个属性必须设置

以上两个是默认就有的

http.cors.enabled:是否支持跨域,默认事false
http.cors.allow-origin:当设置允许跨域,默认为*,表示支持所有域名,如果我们只是允许某些网站能访问,那么可以使用正则表达式。

ElasticSearch入门学习教程_第1张图片

2.2.1.elasticsearch.yml 配置文件

cluster.name: "docker-cluster"
network.host: 0.0.0.0
http.cors.enabled: true
http.cors.allow-origin: "*"

2.2.2.配置好重启容器

# 推出容器
exit
# 重启容器
docker restart es

2.3.浏览器访问localhost:9200

ElasticSearch入门学习教程_第2张图片

上图描述的就是ES的一些基本信息。包括名称、集群名称、集群ID、版本、打开方式、以及依赖程序的版本信息。

3.ElasticSearch目录结构说明

# 通过docker命令进入到容器内部
docker exec -it es /bin/bash
# 查看目录结构
ls -ll

详细如下图所示:

  • LICENSE.txt:证书描述文件
  • NOTICE.txt:产品使用注意事项
  • README.asciidoc:描述或使用文件
  • bin:启动文件
  • config:配置文件
    • log4j2:日志配置文件
    • jvm.options Java虚拟机相关的配置
    • elasticsearch.yml elasticsearch的配置文件
  • lib:相关依赖包
  • logs:日志
  • modules:功能模块
  • plugins:插件

4.使用可视化工具连接ElasticSearch

安装:elasticsearch-head
下载地址:https://github.com/mobz/elasticsearch-head

5.安装Kibana

5.1.Kibana简介

Kibana是一个针对ElasticSearch的开源分析急可视化平台,用来搜索、查看交互存储在ElasticSearch索引中的数据,使用Kibana可以通过各种图标进行高级数据分析及展示。Kibana让海量数据更容易理解。它操作简单,给予浏览器的用户界面可以快速创建仪表板实时显示Elasticsearch查询动态。设置Kibana非常简单。无需编码或者额外的基础架构,几分钟内就可以完成Kibana安装并启动Elasticsearch缩影监测

5.2.Docker安装Kibana

注意:Kibana的版本要和ElasticSearch的版本要保持一致

# 下载7.6.1版本的Kibana镜像
docker pull kibana:7.6.1
# 通过Kibana镜像创建容器,需要注意的是ELASTICSEARCH_URL=http://IP:9200 中的IP是elasticsearch所在服务器的IP
# 可以先通过如下命令获取elasticsearch所在服务器的IP
docker inspect --format '{
     { .NetworkSettings.IPAddress }}' es 
# 我这里得到的IP地址为:172.17.0.2
docker run --name kibana -d -p 5601:5601 --link es -e "ELASTICSEARCH_URL=http://172.17.0.2:9200" kibana:7.6.1

上述操作完成后,在浏览器中访问地址:localhost:5601。如果可以看到如下界面说明Kibana就已经安装好了

如果您访问地址看到的界面如下所示,说明创建的Kibana容器的指向IP没有elasticsearch容器IP。
此时我们可以通过修改Kibana的配置文件来解决这个问题

# 进入到Kibana容器内部
docker exec -it kibana /bin/bash
# 进入配置文件夹
cd config
# 修改kibana.yml配置文件
vi kibana.yml

如下图所示,需要修改elasticsearch.hosts这项配置,将访问的IP修改为elasticsearch服务地址

5.3.使用

ElasticSearch入门学习教程_第3张图片

6.ElasticSearch的核心概念

Elasticsearch是面向文档的非关系型数据库。
关系型数据库和Elasticsearch的客观比较如下:

关系型数据库 Elasticsearch
数据库(database) 索引(indices)
表(table) 类型(types,即将被弃用)
行数据(row) 文档(documents)
字段(columns) 字段(fields)

elasticsearch(集群)中可以包含多个索引(数据库),每一个索引中可以包含多个类型(表),每个类型下又包含多个文档(行),每个文档中又包含多个字段(列)

ES物理设计

elasticsearch在后台吧每个索引分成多个分片,每份分片可以在集群中的不同服务器间迁移

逻辑设计

一个索引类型中,包含多个文档,比如说文档1,文档2.当我们搜索一篇文档时,可以通过这样的一个顺序找到它:
索引 》类型 》文档ID 》通过这个组合我们就能检索到某个具体的文档。

注意:ID不必是整数,实际上它是个字符串

6.1.文档

Elasticserach是面向文档的,那么就意味着索引和搜索数据的最小单位是文档,Elasticsearch,文档有几个重要的属性:

  • 自我包含:一篇文档同时包含字段和对应的值,也就是同时包含key:value
  • 可以是层次型的,一个文档中包含子文档,浮渣的逻辑实体就是这么来的
  • 灵活的结构,文档不依赖预先模式。在关系型数据库中,要提前定义字段才能使用,在elasticsearch中,对于字段是非常灵活的。有时候可以忽略某些字段,或者动态的添加一个新的字段

尽管我们可以随意的增加或者忽略某个字段,但是每个字段的类型非常重要。比如一个年龄字段类型,可以是字符串也可以是整数类型。因为Elasticsearch会保存字段和类型之间的映射及其他的设置。这种映射具体到每一个映射的每种类型,这也是为什么在elasticsearch会保存字段和类型之间的映射及其他的设置。这种映射具体到每个映射的每种类型,这也是为什么在elasticsearch中类型有时候也成为映射类型

6.2.类型

类型是文档的逻辑容器,就像关系型数据库一样,表格是行的容器。类型中对于字段的定义称为映射,比如name映射为字符串类型。我们说文档是无模式的,它不需要拥有映射中所定义的所有字段,比如新增一个字段,那么elasticsearch会自动将新字段加入映射,但是elasticsearch也不知道这个字段是什么类型,于是就会对此进行猜测。如果这个值是18,那么elasticsearch就会认为它是一个整数类型。但是elasticsearch也可能猜不对,所有最安全的方式就是提前的钱定义好所需要的映射。

6.3.索引

索引就是映射关系的容器,elasticsearch中的索引是一个非常大的文档集合。索引存储了映射类型的字段和其他设置,然后它们会被存储到各个分片上。

6.4.物理设计:节点和分片是如何工作的

一个集群至少有一个节点,而一个节点就是一个elasticsearch进程,节点可以有多个索引(默认的)。如果您创建索引,那么索引将会有5个分片(primary shard,又称主分片)构成的,每一个主分片会有一个副本(replica shard,又称复制分片)

ElasticSearch入门学习教程_第4张图片

ElasticSearch入门学习教程_第5张图片

如上图为一个3节点的集群,可以看到主分片对于的复制分片都不会在同一个节点内,这样有利于某个节点意外down机,数据也不会丢失。实际上,一个分片是一个Lucene索引,一个包含到排索引的文件目录,倒排索引的结构使得elasticsearch在不扫描全部文档的情况下,就能告诉你那些文档包含特定的关键字

6.5.倒排索引

Elasticsearch使用的是一种称为倒排索引的结构,采用Lucene倒排索引做为底层。这种结构适用于快速的全文搜索,一个索引由文档中所有不重复的列表构成,对于每一个词,都有一个它的文档列表。例如,现在有两个文档,每个文档包含如下内容:

study every day,good good up to forever # 文档1包含的内容
To forever,study every day,good good up # 文档2包含的内容

为了创建倒排索引,我们首先要每个文档拆分成独立的词(或者称为词条或者tokens),然后创建一个包含所有不重复的词条的排序列表,然后列出每个词条出现在那个文档中

Term doc_1 doc_2
study V X
To X V
every V V
forever V V
day V V
study X V
good V V
every V V
to V X
up V V

现在,我们来搜索一个 to forever,只需要查看包含每个词条的文档

Term doc_1 doc_2
to V X
forever V V
total 2 1

两个文档都匹配,但是第一个文档比第二个匹配程度高。如果没有别的条件,现在,同时包含这两个包含关键字的文档将被返回

倒排索引理解示例:

比如我们通过博客的标签来搜索博客文章,详细如下:

博客文章ID 标签
1 python
2 python
3 Linux python
4 Linux

那么倒排索引列表就是这样的一个结构

标签 博客文章ID
python 1,2,3
Linux 3,4

如果要搜索含有python标签的文章,那相对于查找所有原始数据而言,查找倒排索引的数据将会快很多。只需要查看标签这一栏,然后取到相关的文章ID即可,完全过滤无关的文档。

elasticsearch的索引和Lucene的索引对比

在elasticsearch中,索引这个词被频繁使用,这就是术语的使用,在elasticsearch中,索引被分为多个分片,每份是一个Lucene的索引。所以一个elasticsearch索引是由多个Lucene索引组成的。

7.IK分词器

什么是IK分词器?

分词:即把一段中文或者别的划分成一个个的关键字,我们在搜索的时候会把自己的信息进行分词,会把数据库中的或者索引库中的数据进行分词,然后进行一个匹配操作。默认的中文分词是将每一个字看成一个词。

IK提供两个分词算法:ik_smartik_max_word,其中ik_smart为最少切分,ik_max_word为最细粒度划分!

7.1.安装IK分词器

# 进入到elasticsearch容器里面
docker exec -it es /bin/bash
# 进入到插件目录
cd /usr/share/elasticsearch/plugins
# 下载IK分词器插件(我这里的版本是对应的es版本)
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.6.1/elasticsearch-analysis-ik-7.6.1.zip
# 下载好后退出es容器,重启es容器

7.2.IK分词器使用

使用Kibana测试
ElasticSearch入门学习教程_第6张图片

7.3.分词器扩展字典配置

IK分词器会根据算法去拆分,拆分的依据是根据它默认的一个词库。可能有些自己想连起来的词IK默认的词库达不到要求,此时我们就可以自己去定义一些词库字典。

首先第一步我们先要找到在哪里配置:

# 进入es容器
docker exec -it es /bin/bash
# 进入插件目录
cd /usr/share/elasticsearch/plugins
# 进入IK分词器插件
cd analysis-ik/
# 进入分词器配置目录
cd config/
# 查看分词配置文件
cat IKAnalyzer.cfg.xml

详细操作如下图

现在我们可以自己去创建一个dic字典

# 创建一个自定义分词字典文件
touch myTest.dic

先不着急编写内容,可以先通过Kibana来验证一下。
在kibana中对"text":"good man"进行默认的内容拆分测试,详细如下图所示:

ElasticSearch入门学习教程_第7张图片

现在我想得到的分词中有一项为 good ma,现在可以编辑myTest.dic文件在文件中输入内容:代码ok
配置:

重启elasticsearch和kibana

8.Rest风格说明

8.1.简单介绍

Rest是一种软件风格,而不是一种标准,指数一个一组设计原理和约束条件。它主要用于客户端和服务器交互类的软件。给予这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

基本Rest命令说明:

Method url地址 描述
PUT localhost:9200/索引名称/类型名称/文档ID 创建文档(指定文档ID)
POST localhost:9200/索引名称/类型名称 创建文档(随机文档ID)
POST localhost:9200/索引名称/类型名称/文档ID/_update 修改文档
DELETE localhost:9200/索引名称/类型名称/文档ID 删除文档
GET localhost:9200/索引名称/类型名称/文档ID 查询文档通过文档ID
POST localhost:9200/索引名称/类型名称/_search 查询所有数据

8.2.演示事例

8.2.1.索引相关操作

创建索引

PUT /test1/type1/1
{
     
	"name":"jimmy",
  "age":"21"
}

ElasticSearch入门学习教程_第8张图片

ES中的字段类型

  • 字符串类型

    text(text类型会被分词器解析/拆分)、keyword(keyword类型不会被分词器解析)

  • 数值类型

    long、integer、short、byte、double、float、half、float、scaled、float

  • 日期类型

    date

  • 布尔类型

    boolean

  • 二进制类型

    binary

  • 等等…

创建规则:创建索引时指定字段的类型。

PUT /test2
{
     
  "mappings": {
     
    "properties": {
     
      "name":{
     
        "type":"text"
      },
      "age":{
     
        "type":"integer"
      }
    }
  }
}

获取test2索引的规则信息,通过GET请求获取

GET /test2

ElasticSearch入门学习教程_第9张图片

获取test1索引的规则信息(创建test1索引时没有设置字段类型规则,es会帮我们自动配置)

# 查询索引信息
GET /test1

ElasticSearch入门学习教程_第10张图片

拓展命令

# 获取ES健康值
GET _cat/health
# 查看ES的所有信息
GET _cat/indices?v

ElasticSearch入门学习教程_第11张图片
ElasticSearch入门学习教程_第12张图片

修改文档
修改文档有两种方式:

  • 1、通过再次提交去覆盖原有的值
PUT /test1/type1/1
{
      
  "name":"邪恶的张三",
  "age":23
}

ElasticSearch入门学习教程_第13张图片

  • 2、通过POST:localhost:9200/索引名称/类型名称/文档ID/_update的方式去更新文档中指定字段的值。灵活性更高
POST /test1/type1/1/_update
{
      
  "doc":{
      
    "name":"好人张三"
  }
}

ElasticSearch入门学习教程_第14张图片

删除索引

DELETE test1

8.2.2.查询

# 查询准备数据
# 1.创建索引及字段映射规则
PUT /search_data_list
{
     
  "mappings": {
     
    "properties": {
     
      "name":{
     "type": "text"},
      "age":{
     "type":"integer"},
      "birthday":{
     "type":"date"},
      "tags":{
     "type": "text"}
    }
  }
}
# 2.添加数据
PUT /search_data_list/_doc/1
{
     
  "name":"张三",
  "age":23,
  "birthday":"2021-04-13",
  "tags":["抽烟","喝酒","汤头"]
}

PUT /search_data_list/_doc/2
{
     
  "name":"李四",
  "age":24,
  "birthday":"2021-04-13",
  "tags":["抽烟","喝酒","汤头"]
}

PUT /search_data_list/_doc/3
{
     
  "name":"王五",
  "age":25,
  "birthday":"2021-04-13",
  "tags":["抽烟","喝酒","汤头"]
}

PUT /search_data_list/_doc/4
{
     
  "name":"王五均",
  "age":26,
  "birthday":"2021-04-13",
  "tags":["抽烟","喝酒","汤头"]
}

# 简单查询
# 1.查看索引结构
GET search_data_list
# 2.查看_doc文档下文档ID为2的数据
GET search_data_list/_doc/2
# 3.查询 name=王五 的数据,右边查询出来的_score字段表示数据匹配度,值越大匹配度越高
GET search_data_list/_doc/_search?q=name:王五

# 复杂查询
# query 查询条件结果集
# match 相当于mysql中的and
# _source 结果过滤只取需要的字段
GET search_data_list/_doc/_search
{
     
  "query":{
     
    "match": {
     
      "name": "王五"
    }
  },
  "_source":["name","desc"]
}
# 排序
GET search_data_list/_doc/_search
{
     
  "query":{
     
    "match": {
     
      "name": "王五"
    }
  },
  "sort":{
     
    "age":{
     
      "order":"asc"
    }
  }
}
# 分页
# from 起始值(从0开始)
# size 偏移量
GET search_data_list/_doc/_search
{
     
  "query":{
     
    "match": {
     
      "name": "王五"
    }
  },
  "sort":{
     
    "age":{
     
      "order":"asc"
    }
  },
  "from":0,
  "size":1
}
# 多条件查询
# match > and
# should > or
# must_not > !=
GET search_data_list/_doc/_search
{
     
  "query":{
     
    "bool":{
     
      "must_not":[
        {
     
          "match":{
     "name":"张三"}
        },
        {
     
          "match":{
     "age":23}
        }
      ]
    }
  }
}

# 过滤器
# 使用 filter 对数据进行过滤
# gt大于 gte大于等于 lt小于 lte小于等于
GET search_data_list/_doc/_search
{
     
  "query":{
     
   "bool":{
     
     "must":[
        {
     
          "match":{
     "name":"王五"}
        }  
     ],
    "filter":{
     
      "range":{
     
        "age":{
     
          "lt":26
          }
        }
      }
    }
  }
}

# 精确查询,通过倒排索引指定的词条进行精确查找
# term 直接查询精确的,match 会使用分词器解析(先分析文档,然后再通过分析文档进行查询)
GET search_data_list/_doc/_search
{
     
  "query":{
     
    "term":{
     
      "name":"王"
    }
  }
}

# 多条件精确查询
GET search_data_list/_doc/_search
{
     
  "query":{
     
    "bool":{
     
      "should":[
        {
     
          "term":{
     "age":13}
        },
        {
     
          "term":{
     "age":25}
        }
      ]
  }
}
  
# 高亮查询
GET search_data_list/_doc/_search
{
     
  "query":{
     
    "match":{
     
      "name":"张三"
    }
  },
  "highlight":{
     
    "fields":{
     
      "name":{
     }
    }
  }
}

# 自定义高亮显示
GET search_data_list/_doc/_search
{
     
  "query":{
     
    "match":{
     
      "name":"张三"
    }
  },
  "highlight":{
     
    "pre_tags":"

", "post_tags":"

"
, "fields":{ "name":{ } } } }

9.SpringBoot整合ElasticSearch实现CRUD操作

9.1.导入依赖

导入依赖的时候需要注意,es客户端的版本需要和本地es服务的版本一致。
SpringBoot整合的es默认时使用父工程的版本,所以我们在编写代码前需要去看一下高级的Rest风格的es客户端版本。详细操作如下图:
ElasticSearch入门学习教程_第15张图片

我本地的es服务的版本是7.6.1的,这里依赖父工程的版本是7.6.2。保险请见我需要调整一下es客户端的版本

<properties>
  <java.version>1.8java.version>
  <elasticsearch.version>7.6.1elasticsearch.version>
properties>


<dependency>
  <groupId>org.springframework.bootgroupId>
  <artifactId>spring-boot-starter-data-elasticsearchartifactId>
dependency>

到这一步就可以开始写代码了…

9.2.构建ES客户端实例

package com.scholartang.config;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Author ScholarTang
 * @Date 2021/4/13 2:02 下午
 * @Desc ES 配置类
 */
@Configuration
public class ElasticSearchConfig {
     

    /**
     * 构建一个高级的Rest风格的es客户端实例
     * 一个RestHighLevelClient实例需要一个REST低级别的客户端生成器 来构建如下
     * @return
     */
    @Bean
    public RestHighLevelClient restHighLevelClient(){
     
        return new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
    }
}

9.3.索引相关操作API测试

package com.scholartang;

import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

/**
 * es 7.6.1 高级客户端测试API(索引相关)
 */
@Slf4j
@SpringBootTest
class EsDemoApplicationTests {
     

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 创建索引
     */
    @Test
    void testCreateIndex() throws IOException {
     
        //创建索引请求
        CreateIndexRequest createIndexRequest = new CreateIndexRequest("create_index_01");
        //客户端执行请求
        restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
    }

    /**
     * 获取索引
     */
    @Test
    public void testGetIndex() throws IOException {
     
        //创建获取索引请求
        GetIndexRequest getIndexRequest = new GetIndexRequest("create_index_01");
        //客户端执行请求
        boolean exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
        log.info("索引" + (exists ? "存在" : "不存在"));
    }

    /**
     * 删除索引
     */
    @Test
    public void testDeleteIndex() throws IOException {
     
        //创建删除索引请求
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("create_index_01");
        //客户端执行请求
        restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
    }
}

9.4.文档先关操作API测试

package com.scholartang;

import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

/**
 * es 7.6.1 高级客户端测试API(文档相关)
 */
@Slf4j
@SpringBootTest
class EsDemoApplicationTests {
     
  @Autowired
  private RestHighLevelClient restHighLevelClient;
  
   /** 添加文档 */
  @Test
  public void testAddDocument() throws IOException {
     
    // 创建一个索引请求
    IndexRequest indexRequest = new IndexRequest("create_index_01");
    // 文档ID
    indexRequest.id("1");
    // 设置请求超时时间
    indexRequest.timeout(TimeValue.timeValueMillis(1));
    // 也可以这么写 indexRequest.timeout("60s");
    // 设置文档数据
    indexRequest.source(JSON.toJSONString(new User(1, "张三", "男", 23)), XContentType.JSON);
    // 客户端发送添加文档请求
    IndexResponse index = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
    log.info("IndexResponse:{}", JSON.toJSONString(index));
  }

  /** 获取文档信息 */
  @Test
  public void testGetDocument() throws IOException {
     
    // 创建一个获取请求 get /index/_doc/documentId
    GetRequest getRequest = new GetRequest("create_index_01", "5");
    GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
    if (getResponse.isExists()) {
     
      String source = getResponse.getSourceAsString();
      log.info("source:{}", source);
    }
  }

  /** 更新文档信息 */
  @Test
  public void testUpdateDocument() throws IOException {
     
    // 创建一个更新请求
    UpdateRequest updateRequest = new UpdateRequest("create_index_01", "1");
    updateRequest.timeout("60s");
    updateRequest.doc(JSON.toJSONString(new User(2, "kuang", "女", 23)), XContentType.JSON);
    UpdateResponse updateResponse =
        restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
    log.info("updateStatus:{}", updateResponse.status());
  }

  /** 删除文档 */
  @Test
  public void testDeleteDocument() throws IOException {
     
    // 创建一个删除请求
    DeleteRequest deleteRequest = new DeleteRequest("create_index_01", "1");
    deleteRequest.timeout("60s");
    DeleteResponse deleteResponse =
        restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
    log.info("deleteResponse:{}", deleteResponse.status());
  }

  /** 批量插入文档 */
  @Test
  public void testBathAddDocument() throws IOException {
     
    BulkRequest bulkRequest = new BulkRequest();
    bulkRequest.timeout("60s");
    ArrayList<User> users = new ArrayList<>();
    Collections.addAll(
        users,
        new User(1, "kuang1", "女", 23),
        new User(2, "kuang2", "女", 23),
        new User(3, "kuang3", "女", 23),
        new User(4, "kuang4", "女", 23));
    for (int i = 0; i < users.size(); i++) {
     
      bulkRequest.add(
          // 批量的更新操作和删除操作,在这里修改请求方式即可
          new IndexRequest("create_index_01")
              .id((i + 1) + "")
              .source(JSON.toJSONString(users.get(i)), XContentType.JSON));
    }
    BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
    // 操作是否失败,返回false则为成功
    log.info("bulkResponseStatus:{}", bulkResponse.isFragment());
  }

  /** 批量查询操作 */
  @Test
  public void testBathGetDocument() throws IOException {
     
    // 创建批量查询请求
    SearchRequest searchRequest = new SearchRequest("create_index_01");
    // 构建查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    // QueryBuilders 条件工具类
    // termQuery 精确查询
    TermQueryBuilder termQuery = QueryBuilders.termQuery("name", "kuang1");
    // matchAllQuery 匹配所有
    // MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
    // builder.query(termQuery);
    // 根据文档ID批量查询
    IdsQueryBuilder idsQueryBuilder = new IdsQueryBuilder().addIds("1", "2", "3", "100");
    builder.query(idsQueryBuilder);
    // 设置请求超时时间
    builder.timeout(new TimeValue(60, TimeUnit.SECONDS));
    searchRequest.source(builder);
    // 客户端发起请求
    SearchResponse searchResponse =
        restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    RestStatus status = searchResponse.status();
    if ("ok".equalsIgnoreCase(status.toString())) {
     
      // 所有的结果都是在 SearchHits 里面
      List<Map> maps = new ArrayList<>();
      SearchHits responseHits = searchResponse.getHits();
      SearchHit[] hits = responseHits.getHits();
      for (int i = 0; i < hits.length; i++) {
     
        maps.add(hits[i].getSourceAsMap());
      }
      log.info(JSON.toJSONString(maps));
    }
  }
}

你可能感兴趣的:(elasticsearch,java)