ElasticSearch学习笔记

一、Elasticsearch简述🎇

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

Elasticsearch的主要特点

  1. 全文搜索:它最擅长的是全文搜索。比如,你在一个网站上搜索关键词,Elasticsearch 就能非常快地给出包含这些关键词的内容。
  2. 分布式设计:数据可以分布存储在多台服务器上,这样即使有一台服务器故障,其他服务器也能继续工作,不会影响整体性能。
  3. 实时搜索:Elasticsearch 支持实时数据插入和搜索,数据存储后几乎立即就可以被搜索到。
  4. RESTful API:它使用基于HTTP的RESTful API,这意味着你可以通过网络请求(比如发送 HTTP 请求)与 Elasticsearch 进行交互,查询数据或者存储数据。
  5. 强大的查询能力:除了简单的关键词搜索,它还能进行复杂的数据查询和分析,比如聚合分析、过滤等。

二、使用Docker安装Elasticsearch及相关工具配置🎋

本文基于docker搭建Elasticsearch

创建网络

bash 复制代码
 docker network create es-net

拉取elasticsearch镜像

bash 复制代码
docker pull elasticsearch:7.12.1

运行elasticsearch容器

bash 复制代码
docker run -d --name es -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" -e "discovery.type=single-node" -v E:\ElasticSerach\volume:/usr/share/elasticsearch  --privileged --network es-net -p 9200:9200 -p 9300:9300 elasticsearch:7.12.1

命令解释:

  1. -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" :
    • -e 用于设置环境变量。在这里,ES_JAVA_OPTS 设置了 Elasticsearch 的 Java 虚拟机(JVM)选项。
    • -Xms512m 和 -Xmx512m 分别设置了 JVM 的初始堆大小和最大堆大小为 512MB。
  2. -e "discovery.type=single-node" :
    • 这也是一个环境变量,设置 Elasticsearch 的发现类型为单节点模式。这意味着该实例将作为单个节点运行,而不是集群模式。
  3. -v E:\ElasticSerach\volume:/usr/share/elasticsearch(主机目录可自行替换) :
    • -v 用于挂载卷,将主机上的目录(E:\ElasticSerach\volume)挂载到容器内的 /usr/share/elasticsearch 目录。这使得数据可以在容器重启或删除后保留。
  4. --privileged :
    • 这个选项给予容器额外的权限,允许它执行一些需要特权的操作。通常在需要访问主机资源时使用。
  5. --network es-net :
    • 这部分指定容器连接到名为 es-net 的 Docker 网络,允许与其他容器进行通信。
    • -p 9200:9200 -p 9300:9300:
    • -p 用于将主机的端口映射到容器的端口。这里将主机的 9200 端口映射到容器的 9200 端口(用于 HTTP API),将主机的 9300 端口映射到容器的 9300 端口(用于集群内部通信)。
  6. elasticsearch:7.12.1 :
    • 这是要运行的镜像名称和标签,指定使用 Elasticsearch 的 7.12.1 版本。

容器运行成功后,访问本地9200(http://localhost:9200/)端口,会出现以下json文本%25E7%25AB%25AF%25E5%258F%25A3%25EF%25BC%258C%25E4%25BC%259A%25E5%2587%25BA%25E7%258E%25B0%25E4%25BB%25A5%25E4%25B8%258Bjson%25E6%2596%2587%25E6%259C%25AC "http://localhost:9200/)%E7%AB%AF%E5%8F%A3%EF%BC%8C%E4%BC%9A%E5%87%BA%E7%8E%B0%E4%BB%A5%E4%B8%8Bjson%E6%96%87%E6%9C%AC")

json 复制代码
{
  "name": "36aaa71ec269",
  "cluster_name": "docker-cluster",
  "cluster_uuid": "xMJHFh66RYWE3Lok_H5SXw",
  "version": {
    "number": "7.12.1",
    "build_flavor": "default",
    "build_type": "docker",
    "build_hash": "3186837139b9c6b6d23c3200870651f10d3343b7",
    "build_date": "2021-04-20T20:56:39.040728659Z",
    "build_snapshot": false,
    "lucene_version": "8.8.0",
    "minimum_wire_compatibility_version": "6.8.0",
    "minimum_index_compatibility_version": "6.0.0-beta1"
  },
  "tagline": "You Know, for Search"
}

拉取kibana镜像

Kibana 是一个开源的数据可视化和分析工具,通常与 Elasticsearch 一起使用,可以可视化Elasticsearch 中的数据

bash 复制代码
 docker pull kibana:7.12.1

运行kibana容器

bash 复制代码
#此处网络需要和上文创建的网络保持一致,这样Kibana和elasticsearch才能在同一网络下
docker run -d --name kibana -e ELASTICSEARCH_HOSTS=http://es:9200 --network=es-net -p 5601:5601 kibana:7.12.1

访问本地5601端口,可进入可视化界面,其自带dev tools

拉取elasticsearch-head镜像

bash 复制代码
docker pull mobz/elasticsearch-head:5

创建elasticsearch-head容器

bash 复制代码
docker create --name elasticsearch-head --network es-net -p 9100:9100 mobz/elasticsearch-head:5

修改elasticsearch的配置

注意:是修改elasticsearch容器的配置,此处是因为elasticsearch和elasticsearch-head存在跨域问题。

进入elasticsearch容器

记得修改为自己的容器号

bash 复制代码
docker exec -it 36aaa71ec269 /bin/bash
shell 复制代码
vi config/elasticsearch.yml
#添加以下配置
http.cors.enabled: true
http.cors.allow-origin: "*"

访问本地9200端口

三、Elasticsearch核心概念🎍

Elasticsearch是==面向文档==

维度 Elasticsearch 关系型数据库(MySQL、PostgreSQL)
基本单位 索引(Index) 数据库(Database)
数据结构 文档(Document) 表(Table)
记录单位 文档(Document) 行(Row)
属性单位 字段(Field) 列(Column)
数据存储方式 JSON 格式(NoSQL,非结构化) 关系型表结构(结构化数据)
查询语言 查询 DSL(Domain-Specific Language) SQL(Structured Query Language)
数据关系 不支持直接的表间关系(如外键) 支持(如外键、联结操作)
扩展性 水平扩展(分片,适用于海量数据) 垂直扩展(增加硬件资源)
适用场景 全文搜索、日志分析、实时数据查询 事务处理、数据分析、多表联结查询
索引 每个字段都会自动建立倒排索引 可自定义索引,通常单列、多列索引
事务支持 不支持 ACID 事务(仅部分操作有原子性) 支持 ACID 事务
数据一致性 最终一致性 强一致性
灵活性 无需预定义数据模式,可动态添加字段 必须预定义数据表的结构
聚合操作 支持复杂的聚合和统计操作 支持 SQL 聚合查询(如 GROUP BY)
数据更新 部分更新时,整个文档需要重新索引 可直接更新行中的某个字段
全文搜索 内置强大的全文搜索功能 需要额外配置,通常性能较低
复制与分片 支持内置的分片和副本机制 需要手动配置主从复制
高可用性 自动分片和副本,天然支持高可用 通过主从复制和集群架构实现

物理设计: elasticsearch在后台把每个索引划分成多个分片,每分分片可以在集群中的不同服务器间迁移。

一台实例就是一个集群

逻辑涉及:

一个索引类型中,包含多个文档,比如说文档1,文档2。当我们索引一篇文档时,可以通过这样的一各顺序找到它:索引--->类型--->文档ID,通过这个组合我们就能索引到某个具体的文档。注意:ID不必是整数,实际上它是个字符串。

文档

文档是 Elasticsearch 中存储数据的==基本单位==,相当于关系型数据库中的一行记录。它以 JSON 格式表示,包含一组相关的字段,用来描述某个实体,如一个用户的信息。文档结构非常灵活,可以包含简单字段(如文本、数字)或复杂的嵌套对象和数组,不需要预先固定格式。每个文档存储在一个索引中,并拥有唯一的 ID。为了高效查询,Elasticsearch 使用映射来定义文档中字段的属性。

类型(7版本已废弃)

在早期版本的 Elasticsearch(6.x 及之前),类型(Type) 是一个用于区分同一索引中不同数据类别的概念。它类似于关系型数据库中的表,可以在一个索引中存储多种不同结构的文档。例如,一个索引可以包含两种类型的文档:user 和 order,分别用来存储用户信息和订单信息。

每个文档都会被分配一个类型,使得同一索引中可以存储多种不同结构的数据。然而,所有类型共享同一个索引的存储空间,这带来了以下问题:

  1. 字段冲突:如果不同类型中的字段名称相同但数据类型不同(例如,name字段在 User 类型中是字符串,而在 Order 类型中是数字),会导致存储和查询的冲突。
  2. 复杂性:底层存储中,一个索引只能有一个倒排索引和数据结构。类型之间的混合会使数据管理复杂化。

索引

类比为一个数据库

索引(Index) 在 Elasticsearch 中是一个用于组织和存储数据的逻辑结构。它包含一组具有相似特征的文档,并为这些文档创建一个==倒排索引==,从而支持快速、高效的搜索和分析。索引就像一本书的目录,帮助 Elasticsearch 快速找到相关的数据。每个索引都有一个唯一的名称,用于在存储和查询时进行标识。

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

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

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

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

倒排索引

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

bash 复制代码
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 ×
To × ×
every
forever
day
study ×
good
every ×
to
up ×

四、Ik分词器🎊

什么是ik分词器

分词:即把一段中文或者别的划分成一个个的关键字,我们在搜索时候会把自己的信息进行分词,会把数据库中或者索引库中的数据进行分词,然后进行一个匹配操作,默认的中文分词是将每个字看成一个词,比如"你好世界"会被分为"你"、"好"、"世"、"界",这显然是不符合要求的,所以我们需要安装中文分词器ik来解决这个问题。

Ik提供了两个分词算法:ik_smart和ik_max_word,其中ik_smart为最少切分,ik_max_word为最细粒度划分。

ik分词器-Github下载地址

将下载的ik分词器下载后并解压至es挂载的es-plugins目录下,并重启es容器

在kibana中使用

ik_smart为最少切分

json 复制代码
GET _analyze
{
  "analyzer": "ik_smart",
  "text": "世界人民大团结万岁"
}

#分词结果
{
  "tokens" : [
    {
      "token" : "世界人民",
      "start_offset" : 0,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "大团结",
      "start_offset" : 4,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "万岁",
      "start_offset" : 7,
      "end_offset" : 9,
      "type" : "CN_WORD",
      "position" : 2
    }
  ]
}

ik_max_word为最细粒度划分

json 复制代码
GET _analyze
{
  "analyzer": "ik_max_word",
  "text": "世界人民大团结万岁"
}

#分词结果
{
  "tokens" : [
    {
      "token" : "世界人民",
      "start_offset" : 0,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "世界人",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "世界",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "人民",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 3
    },
    {
      "token" : "大团结",
      "start_offset" : 4,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 4
    },
    {
      "token" : "大团",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 5
    },
    {
      "token" : "团结",
      "start_offset" : 5,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 6
    },
    {
      "token" : "万岁",
      "start_offset" : 7,
      "end_offset" : 9,
      "type" : "CN_WORD",
      "position" : 7
    },
    {
      "token" : "万",
      "start_offset" : 7,
      "end_offset" : 8,
      "type" : "TYPE_CNUM",
      "position" : 8
    },
    {
      "token" : "岁",
      "start_offset" : 8,
      "end_offset" : 9,
      "type" : "COUNT",
      "position" : 9
    }
  ]
}

自定义ik分词器配置

创建自定义词典test.dic

测试

ik_smart为最少切分

ik_max_word为最细粒度划分

此处笑的像个两百斤的孩子变成了一个完整的词语。

五、Rest风格说明🎪

RESTful 是一种基于 REST(Representational State Transfer,表述性状态转移)架构风格的==设计原则==,通常用于设计网络服务的 API。RESTful 的核心理念是通过 HTTP 协议进行通信,将系统的资源进行统一的表示,并通过不同的 HTTP 方法来操作这些资源。

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 查询所有数据

创建索引

查询索引

更新索引

删除索引

六、构建复杂查询🎢

查询的参数体使用json构建

普通查询

json 复制代码
GET /test/_search
{
  "query": {
    "match": {
      "name": "testname2"
    }
  }
}

#查询结果
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.9808291,
    "hits" : [
      {
        "_index" : "test",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.9808291,
        "_source" : {
          "name" : "testname2",
          "age" : 32,
          "tags" : [
            1,
            4,
            5,
            6
          ]
        }
      }
    ]
  }
}

模糊查询

json 复制代码
GET /test/_search
{
  "query": {
    "fuzzy": {
      "name": {
        "value": "testname"
      }
    }
  }
}

#查询结果
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 0.9808291,
    "hits" : [
      {
        "_index" : "test",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.9808291,
        "_source" : {
          "name" : "testname",
          "age" : 22,
          "tag" : [
            1,
            2,
            3,
            4,
            5,
            6
          ]
        }
      },
      {
        "_index" : "test",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.8582256,
        "_source" : {
          "name" : "testname2",
          "age" : 32,
          "tags" : [
            1,
            4,
            5,
            6
          ]
        }
      },
      {
        "_index" : "test",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.8582256,
        "_source" : {
          "name" : "testname3",
          "age" : 42,
          "tags" : [
            1,
            4,
            5
          ]
        }
      }
    ]
  }
}

通过前缀模糊查询,并且指定需要查询的字段类似(select name,age from xxxx),且根据年龄将结果倒序,且进行分页

json 复制代码
GET /test/_search
{
  "query": {
    "prefix": {
      "name": {
        "value": "test"
      }
    }
  },
  "_source": ["name","age"],
  "sort": [
    {
      "age": {
        "order": "desc"
      }
    }
  ],
  "from": 0,
  "size": 3
}

#查询结果
{
  "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" : "test",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : null,
        "_source" : {
          "name" : "testname3",
          "age" : 42
        },
        "sort" : [
          42
        ]
      },
      {
        "_index" : "test",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : null,
        "_source" : {
          "name" : "testname2",
          "age" : 32
        },
        "sort" : [
          32
        ]
      },
      {
        "_index" : "test",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : null,
        "_source" : {
          "name" : "testname",
          "age" : 22
        },
        "sort" : [
          22
        ]
      }
    ]
  }
}

参数解释:

  1. GET /test/_search
  • 这表示对索引 test 进行搜索查询。
  1. "query": { "prefix": { "name": { "value": "test" } } }
  • prefix 查询:搜索以指定前缀开头的文档。这种查询会匹配 name 字段中以 "test" 开头的值。例如,如果文档中有 name 字段的值是 "test123"、"testing" 等,它们都会被匹配到。
  • "name":这是要匹配前缀的字段名称。
  • "value": "test":指定前缀值为 "test"。
  1. "_source": ["name", "age"]
  • 这个部分用来指定返回结果中包含的字段。此处只会返回 name 和 age 字段,其他字段将被省略。
  1. "sort": [ { "age": { "order": "desc" } } ]
  • 用于排序查询结果。
  • "age":按照 age 字段进行排序。
  • "order": "desc":表示降序排序,值越大的文档排在前面。
  1. "from": 0, "size": 3
  • "from":表示从第几条数据开始返回,类似于分页查询的起始位置。0 表示从第一条数据开始。
  • "size":表示返回的文档数量。此处设置为 3,即最多返回 3 条匹配的文档。

七、SpringBoot集成ES✨

7.1 操作索引API

ES-client的Java集成文档

创建工程并引入依赖

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>es-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>es-demo</name>
    <description>es-demo</description>
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.12.RELEASE</spring-boot.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.40</version>
        </dependency>
        
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        
    </dependencies>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <configuration>
                    <mainClass>com.example.esdemo.EsDemoApplication</mainClass>
                    <skip>true</skip>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

创建配置类

java 复制代码
@Configuration
public class ESClientConfig {
    @Bean
    public RestHighLevelClient highLevelClient() {
        return new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("localhost", 9200, "http")));
    }
}

单元测试操作索引的API

java 复制代码
@SpringBootTest
class EsDemoApplicationTests {
    @Autowired
    RestHighLevelClient esClient;
    /**
     * 索引名称
     */
    private final String INDEX_NAME = "test_index";

    /**
     * 创建索引
     */
    @Test
    void testCreateIndex() throws IOException {
        CreateIndexRequest testIndex = new CreateIndexRequest(INDEX_NAME);
        CreateIndexResponse createIndexResponse = esClient.indices().create(testIndex, RequestOptions.DEFAULT);
        System.out.println(createIndexResponse);
    }

    /**
     * 获取索引
     */
    @Test
    void testGetIndex() throws IOException {
        GetIndexRequest getIndexRequest = new GetIndexRequest(INDEX_NAME);
        //判断索引是否存在
        boolean exists = esClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
        if (exists) {
            GetIndexResponse getIndexResponse = esClient.indices().get(getIndexRequest, RequestOptions.DEFAULT);
            System.out.println(true);
            System.out.println(getIndexResponse);
        } else {
            System.out.println(false);
        }
    }

    /**
     * 删除索引
     */
    @Test
    void testDeleteIndex() throws IOException {
        AcknowledgedResponse testIndex = esClient.indices().delete(new DeleteIndexRequest(INDEX_NAME), RequestOptions.DEFAULT);
        System.out.println(testIndex.isAcknowledged());
    }
}

7.2 操作文档API

java 复制代码
/**
 * @Author YZK
 * @Date 2024/9/22
 * @Desc
 */
@SpringBootTest
public class EsDemoApplicationDocTests {
    @Autowired
    RestHighLevelClient esClient;
    /**
     * 索引名称
     */
    private final String INDEX_NAME = "test_index";


    /**
     * 添加文档
     */
    @Test
    void testAddDocument() throws IOException {
        Document document = new Document("2", "内容2", "标题2");
        IndexRequest indexRequest = new IndexRequest(INDEX_NAME);
        //Put /test_index/_doc/1
        indexRequest.id(document.getId());
        indexRequest.timeout(TimeValue.timeValueSeconds(1));
        String jsonString = JSON.toJSONString(document);
        indexRequest.source(jsonString, XContentType.JSON);
        //客户端发送请求
        IndexResponse indexResponse = esClient.index(indexRequest, RequestOptions.DEFAULT);
        System.out.println(indexResponse.toString());
        System.out.println(indexResponse.status());
    }

    /**
     * 获取文档的信息
     */
    @Test
    void testGetDocument() throws IOException {
        GetRequest getRequest = new GetRequest(INDEX_NAME, "1");
        GetResponse getResponse = esClient.get(getRequest, RequestOptions.DEFAULT);
        System.out.println(getResponse.getSourceAsString());
        System.out.println(getResponse);
    }

    /**
     * 全量搜索文档信息并分页
     */
    @Test
    void testSearchDocument() throws IOException {
        SearchRequest searchRequest = new SearchRequest("test_index");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery())
                .from(0)
                .size(1);
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);
        searchResponse.getHits().forEach(item -> System.out.println(item.getSourceAsMap()));
    }

    /**
     * 精确搜索文档
     */
    @Test
    void testSearchTrimDocument() throws IOException {
        SearchRequest searchRequest = new SearchRequest("test_index");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.termQuery("id","3"));
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);
        searchResponse.getHits().forEach(item -> System.out.println(item.getSourceAsMap()));
    }

    /**
     * 更新文档信息
     */
    @Test
    void testUpdateDocument() throws IOException {
        Document document = new Document("1", "更新内容", "更新标题");
        UpdateRequest updateRequest = new UpdateRequest("test_index", "1");
        updateRequest.doc(JSON.toJSONString(document), XContentType.JSON);
        UpdateResponse updateResponse = esClient.update(updateRequest, RequestOptions.DEFAULT);
        System.out.println(updateResponse.status());
    }

    /**
     * 删除文档信息
     */
    @Test
    void testDeleteDocument() throws IOException {
        DeleteRequest deleteRequest = new DeleteRequest("test_index", "2");
        DeleteResponse deleteResponse = esClient.delete(deleteRequest, RequestOptions.DEFAULT);
        System.out.println(deleteResponse.status());
    }

    /**
     * 批量插入数据
     */
    @Test
    void testBatchInsert() throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        List<Document> documentList=new ArrayList<>();
        documentList.add(new Document("3", "内容3", "标题3"));
        documentList.add(new Document("4", "内容4", "标题4"));
        documentList.forEach(item -> bulkRequest.add(new IndexRequest(INDEX_NAME)
                //不指定id就会生成随机id
                .id(item.getId())
                .source(JSON.toJSONString(item), XContentType.JSON)));
        BulkResponse bulkResponse = esClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        System.out.println(bulkResponse.status());
    }
}
相关推荐
woshiabc11125 分钟前
windows安装Elasticsearch及增删改查操作
大数据·elasticsearch·搜索引擎
lucky_syq1 小时前
Saprk和Flink的区别
大数据·flink
lucky_syq1 小时前
流式处理,为什么Flink比Spark Streaming好?
大数据·flink·spark
袋鼠云数栈1 小时前
深入浅出Flink CEP丨如何通过Flink SQL作业动态更新Flink CEP作业
大数据
AskHarries2 小时前
Spring Cloud OpenFeign快速入门demo
spring boot·后端
小白学大数据2 小时前
如何使用Selenium处理JavaScript动态加载的内容?
大数据·javascript·爬虫·selenium·测试工具
15年网络推广青哥3 小时前
国际抖音TikTok矩阵运营的关键要素有哪些?
大数据·人工智能·矩阵
isolusion3 小时前
Springboot的创建方式
java·spring boot·后端
zjw_rp3 小时前
Spring-AOP
java·后端·spring·spring-aop
节点。csn3 小时前
Hadoop yarn安装
大数据·hadoop·分布式