ElasticSearch完整入门及springboot集成

news2024/11/24 7:14:44

目录

  • ElasticSearch概述
  • ElasticSearch版本特性
    • Elasticsearch 5
    • Elasticsearch 6.0
    • Elasticsearch 7.0
    • Elasticsearch 8.0
  • ElasticSearch安装
    • Windows
    • linux
  • Kibana安装
    • Windows
    • linux
    • 使用
  • IK分词器(elasticsearch插件)
    • 安装
    • 自定义的词典
  • ES的基本使用
    • 字段数据类型
    • 索引操作
    • 文档操作
      • 创建文档
      • 查看文档
      • 修改文档
      • 删除文档
      • 复杂查询
        • 查询匹配(匹配、过滤、排序、分页)
        • 多条件查询(must、should、filter)
        • match和term查询
        • wildcard查询
        • 高亮查询
  • SpringBoot整合ES
  • 参考链接

ElasticSearch概述

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

据国际权威的数据库产品评测机构DB Engines的统计,在2016年1月,ElasticSearch已超过Solr等,成为排名第一的搜索引擎类应用。

ElasticSearch版本特性

tip:es的版本7x和8x差别很大,安装和使用也存在差异,本文针对的7x版本的,强烈建议学习使用7x版本的

Elasticsearch 5

首先说明下,ES是从版本2直接跳到5的,主要是为了和Elastic Stack其他组件保持版本一致
ES5,在现在来说是比较老的版本了,就不多介绍了
建议大家使用ES7

Elasticsearch 6.0

  1. 移除type,在 6.0 里面,开始不支持一个 index 里面存在多个 type 了,所有的新的 index 都将只有一个虚拟的固定的 type: doc 来代替

  2. 稀疏性 Doc Values 的支持, es 的 doc values 是列式存储,文档的原始值都是存放在 doc values 里面的,优化了一个文档有的字段其他文档的持有开销

  3. Index sorting,即在索引阶段的排序支持,索引的时候会要增加额外开销,适合不怎么变化的索引的场景。

  4. 已经关闭的索引将也支持 replica 的自动处理,确保数据可靠

  5. Load aware shard routing, 基于负载的请求路由,目前的搜索请求是全节点轮询,那么性能最慢的节点往往会造成整体的延迟增加,新的实现方式将基于队列的耗费时间自动调节队列长度,负载高的节点的队列长度将减少,让其他节点分摊更多的压力,搜索和索引都将基于这种机制。

  6. 顺序号的支持,每个 es 的操作都有一个顺序编号(类似增量设计)无缝滚动升级

Elasticsearch 7.0

  1. ES 数据库的存储结构变化:去除了Type,包括API层面

  2. 默认配置变化:默认节点名称为主机名,默认分片数为1,不再是5

  3. 查询相关速度优化:Weak-AND算法。又称为Wand算法, 输入是n个倒排队列,输出top K个得分最高的文档doc,weak-and算法通过计算每个词的贡献上限来估计文档的相关性上限,从而建立一个阈值对倒排中的结果进行减枝,从而得到提速的效果。

  4. 彻底废除 _all 字段的支持,为提升性能默认不在支持全文检索

  5. 集群连接变化:TransportClient被废弃,对于java编程,建议采用 High-level-rest-client 的方式

  6. ES程序包默认打包jdk:以至于7.x版本的程序包大小突然边300MB+

  7. 间隔查询(Intervals queries),Elasticsearch 7.0中的间隔查询引入了一种构建“单词或短语彼此相距一定距离的记录查询”的需要的全新方式,与之前的方法(跨度查询span queries)相比,使用和定义更加简单。

  8. 函数分数 2.0,通过新的模块化结构,用户能够混合和匹配一组算术和距离函数,从而构建任意的函数分数计算方式,进而在更大程度上控制结果的评分和排名方式。

  9. 引入新的集群协调子系统,移除 minimum_master_nodes 参数,让 Elasticsearch 自己选择可以形成仲裁的节点。

  10. 典型的主节点选举现在只需要很短的时间就可以完成。集群的伸缩变得更安全、更容易,并且可能造成丢失数据的系统配置选项更少了。 节点更清楚地记录它们的状态,有助于诊断为什么它们不能加入集群或为什么无法选举出主节点。

  11. 不再内存溢出,新的 Circuit Breaker 在JVM 堆栈层面监测内存使用,Elasticsearch 比之前更加健壮。设置indices.breaker.fielddata.limit的默认值已从JVM堆大小的60%降低到40%。

  12. 支持达到纳秒级精度,强化时序型用例

  13. 支持达到纳秒级精度,强化时序型用例

  14. Lucene9.0的支持

  15. 7.1开始,Security功能免费使用

Elasticsearch 8.0

Elasticsearch 8.0 版通过改进 Elasticsearch 的矢量搜索功能、对现代自然语言处理模型的原生支持、不断简化的数据上线过程,以及精简的安全防护体验,在速度、扩展幅度、相关性和简便性方面,迎来了一个全新的时代。需要 Java 17 才能运行 Elasticsearch。

Elasticsearch 8.0 版是基于 Lucene 9.0 开发的,那些利用现代 NLP 的搜索体验,都可以借助(新增的)对近似最近邻搜索的原生支持,快速且大规模地实现。通过 ANN,可以快速并高效地将基于矢量的查询与基于矢量的文档语料库(无论是小语料库、大语料库还是巨型语料库)进行比较。

重要更新

  1. Rest API相比较7.x而言做了比较大的改动(比如彻底删除_type),为了降低用户的升级成本,8.x会暂时的兼容7.x的请求。
  2. 默认开启安全配置(三层安全),并极大简化了开启安全需要的工作量,可以这么说:7.x开启安全需要10步复杂的步骤比如CA、证书签发、yml添加多个配置等等,8.x只需要一步即可)。
  3. 存储空间优化:更新了倒排索引,对倒排文件使用新的编码集,对于keyword、match_only_text、text类型字段有效,有3.5%的空间优化提升,对于新建索引和segment自动生效。
  4. 优化geo_point,geo_shape类型的索引(写入)效率:15%的提升。
  5. 新特性:支持上传pyTorch模型,在ingest的时候使用。比如在写入电影评论的时候,如果我们想要知道这个评论的感情正负得分,可以使用对应的AI感情模型对评论进行运算,将结果一并保存在ES中。
  6. 技术预览版KNN API发布,(K邻近算法),跟推荐系统、自然语言排名相关。之前的KNN是精确搜索,在大数据集合的情况会比较慢,新的KNN提供近似KNN搜索,以提高速度。
  7. 对ES内置索引的保护加强了:elastic用户默认只能读,如果需要写权限的时候,需有allow_restrict_access权限

ElasticSearch安装

Kibana是ElasticSearch的可视化工具,建议下载7.X版本的,8.x版本改动很多,学习成本很大,这篇文章也是针对7.x版本的

Windows

需要注意的的elasticsearch和kibana版本要一致

下载地址:https://www.elastic.co/cn/downloads/elasticsearch
在这里插入图片描述
解压即可

kibana下载地址:https://www.elastic.co/cn/downloads/kibana

在这里插入图片描述
也是解压就行
在这里插入图片描述

bin 启动文件目录
config 配置文件目录
    1og4j2 日志配置文件
    jvm.options java 虚拟机相关的配置(默认启动占1g内存,内容不够需要自己调整)
    elasticsearch.ym1 elasticsearch 的配置文件! 默认9200端口!跨域!
1ib 
    相关jar包
modules 功能模块目录
plugins 插件目录
    ik分词器

运行与访问

双击elasticsearch.bat运行即可

在这里插入图片描述
在这里插入图片描述

访问

http://127.0.0.1:9200/

在这里插入图片描述

linux

centos7安装es可以有多种方式,下面演示的是通过wget方式下载

安装wget命令

yum -y install wget

wget命令下载es到指定目录

##es的安装目录
cd /usr/local
## 下载es压缩包
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.6.1-linux-x86_64.tar.gz
##解压
tar -zxvf elasticsearch-7.6.1-linux-x86_64.tar.gz

上面es的下载地址可以去官网复制
在这里插入图片描述
下载并解压成功
在这里插入图片描述
配置并启动
新建data目录存放es数据

mkdir /usr/local/elasticsearch-7.6.1/data

修改config/elasticsearch.yml,

vi  elasticsearch-7.6.1/config/elasticsearch.yml

在文件最后面加入以下内容,esc后:wq退出并保存

#设置绑定的ip,设置为0.0.0.0以后就可以让任何计算机节点访问到了
network.host: 0.0.0.0
http.port: 9200 #端口
#数据和日志的存储目录
path.data: /usr/local/elasticsearch-7.6.1/data
path.logs: /usr/local/elasticsearch-7.6.1/logs
#设置在集群中的所有节点名称,默认节点是node-1
node.name: node-1
#discovery.seed_host: [192.168.0.116]
cluster.initial_master_nodes: ["node-1"]

ES从5.几之后便不能用root用户进行启动了所以必须要建一个用户。用新用户连接并启用es才行

添加es新用户

adduser es

为es用户设置密码

passwd es

输入新的密码和确认密码

修改es目录所属用

chown es /usr/local/elasticsearch-7.6.1 -R
chown -R es:es /usr/local/elasticsearch-7.6.1

vi 编辑 /etc/security/limits.conf

vi /etc/security/limits.conf

在末尾加上

es soft nofile 65536
es hard nofile 65536
es soft nproc 4096
es hard nproc 4096

vi 编辑 vi /etc/security/limits.d/20-nproc.conf,将* 改为用户名(es)

vi /etc/security/limits.d/20-nproc.conf

在这里插入图片描述
查询上面的配置是否生效

加了上面修改后需要重新连接服务器才能生效,新建ssh连接后执行命令

ulimit -a

在这里插入图片描述
如上变成4096说明配置生效

vi 编辑 /etc/sysctl.conf,在末尾加上:

vm.max_map_count = 655360

执行下面命令,使sysctl.conf配置文件生效

sysctl -p

开放es端口

##开放9200端口
firewall-cmd --permanent --zone=public --add-port=9200/tcp
##重启防火墙
systemctl reload firewalld
##查看开放的端口
firewall-cmd --list-ports

切换es用户启动es

##前台启动
/usr/local/elasticsearch-7.6.1/bin/elasticsearch
##后台启动
/usr/local/elasticsearch-7.6.1/bin/elasticsearch -d

关闭es,先查询es的进程号再用kill命令强制关闭

ps -ef|grep elasticsearch

启动成功访问 http://ip:9200/
在这里插入图片描述

Kibana安装

Windows

Kibana和es一样也是下载解压运行就行

下载的版本需要与ElasticSearch版本对应

下载地址:https://www.elastic.co/cn/downloads/past-releases/kibana-7-6-1
在这里插入图片描述
下载解压即可

汉化
编辑器打开kibana解压目录/config/kibana.yml,添加

i18n.locale: "zh-CN"

双击bin目录的kibana.bat就行
在这里插入图片描述
访问

http://127.0.0.1:5601/

在这里插入图片描述

linux

wget命令下载kibana到指定目录

##es的安装目录
cd /usr/local
## 下载es压缩包
wget https://artifacts.elastic.co/downloads/kibana/kibana-7.6.1-linux-x86_64.tar.gz
##解压
tar -zxvf kibana-7.6.1-linux-x86_64.tar.gz

上面kibana的下载地址可以去官网复制
在这里插入图片描述

配置
修改kibana的config目录里面的kibana.yml文件,在文件最后面加

#配置端口号
server.port: 5601
#配置网络访问地址
server.host: "0.0.0.0"
#配置es链接地址(es集群,可以用逗号分隔),ip设置你的服务器ip
elasticsearch.hosts: ["http://192.168.100.110:9200"]
#配置中文语言界面
i18n.locale: "zh-CN"

修改目录权限
将kibana的目录权限改为es用户的,如果还没添加es用户可以去elasticsearch的linux安装中按步骤添加es用户

chown -R es:es /usr/local/kibana-7.6.1-linux-x86_64

开放kibana端口

##开放5601端口
firewall-cmd --permanent --zone=public --add-port=5601/tcp
##重启防火墙
systemctl reload firewalld
##查看开放的端口
firewall-cmd --list-ports

启动

注意必须使用普通用户启动服务 root用户启动会报错,并且elasticsearch必须先启动

切换es用户启动

#前台启动
/usr/local/kibana-7.6.1-linux-x86_64/bin/kibana
#后台启动
nohup /usr/local/kibana-7.6.1-linux-x86_64/bin/kibana >/usr/local/kibana-7.6.1-linux-x86_64/kiban.log 2>&1 &

访问

http://192.168.100.110:5601/

在这里插入图片描述

使用

查看索引
在Management下的索引管理里查看目前es的全部索引
在这里插入图片描述

在这里插入图片描述

查看索引的文档
第一步先创建索引模式
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

IK分词器(elasticsearch插件)

安装

版本要与ElasticSearch版本对应

下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases

在这里插入图片描述

找到要下载的版本,不管你的es是安装在windows还是linux都是下载的zip文件,然后将解压后的文件放在es新建的ik文件夹,再重启es就行,Windows和linux都是一个道理

#在es的plugins目录下新建ik文件夹
mkdir /usr/local/elasticsearch-7.6.1/plugins/ik
cd  /usr/local/elasticsearch-7.6.1/plugins/ik
#下载ik压缩包
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.6.1/elasticsearch-analysis-ik-7.6.1.zip
#安装unzip
yum install unzip
#解压缩
unzip elasticsearch-analysis-ik-7.6.1.zip

经过上面的操作,ik目录就变成了这样
在这里插入图片描述

然后重启es
在这里插入图片描述
启动日志如图所示,说明ik分词器加载成功

在kibana上测试ik分词器
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

IK的 ik_smart 和 ik_max_word两种模式

ik_smart(最少切分):分词的时候只分一次,句子里面的每个字只会出现一次

ik_max_word(最细粒度划分(穷尽词库的可能)):句子的字可以反复出现。 只要在词库里面出现过的
就拆分出来。如果没有出现的单字。如果已经在词里面出现过,那么这个就不会以单字的形势出现

需要注意的是es加载了IK分词器并不代表es的的索引和文档都会使用IK分词器,安装IK分词器只是提供了一种选择,你可以在创建文档时选择使用IK分词器,如果不指定会默认使用es内置的标准分词器(Standard Analyzer)进行分词,这种分词器对中文不友好

自定义的词典

在elasticsearch目录/plugins/ik/config 添加自定义字典my.dic
在这里插入图片描述

添加内容
在这里插入图片描述
修改elasticsearch目录/plugins/ik/config/IKAnalyzer.cfg.xml文件
在这里插入图片描述
在这里插入图片描述
重启es测试

ES的基本使用

字段数据类型

字符串类型
text、keyword
text:支持分词,全文检索,支持模糊、精确查询,不支持聚合,排序操作;text类型的最大支持的字符长度无限制,适合大字段存储;
keyword:不进行分词,直接索引、支持模糊、支持精确匹配,支持聚合、排序操作。keyword类型的最大支持的长度为——32766个UTF-8类型的字符,可以通过设置ignore_above指定自持字符长度,超过给定长度后的数据将不被索引,无法通过term精确匹配检索返回结果。
数值型
long、Integer、short、byte、double、float、half float、scaled float
日期类型
date
te布尔类型
boolean
二进制类型
binary

索引操作

#创建索引
put /es_db

#查询索引
get es_db

#删除索引
delete es_db

#查询索引是否存在
HEAD es_db

#关闭索引
post /es_db/_close

#打开索引
post /es_db/_open

文档操作

创建文档

put、post、_create都可以创建文档,put要指定id,post也可以跟put一样创建文档,区别是post如果不指定id的话es会自动生成,_create如果id有存在会添加失败

#put添加文档
PUT /es_db/_doc/1
{
  "name":"张三",
  "sex":1,
  "age":25,
  "address":"广州天河公园",
  "remake":"java developer"
}


#post添加文档
POST /es_db/_doc
{
  "name":"张三2",
  "sex":1,
  "age":25,
  "address":"广州天河公园",
  "remake":"java developer"
}

POST /es_db/_doc/1
{
  "name":"张三2",
  "sex":1,
  "address":"广州天河公园",
  "remake":"java developer"
}

#_create添加文档

PUT /es_db/_create/1
{
  "name":"张三2",
  "sex":1,
  "address":"广州天河公园",
  "remake":"java developer"
}

查看文档

#根据ID查询指定文档
GET /es_db/_doc/1
#查询索引的全部文档
GET /es_db/_search

修改文档

tip:post和put覆盖更新都是会删除原来的文档再插入,会导致文档的属性丢失,_update是局部更新,只会更新选择的属性不会丢失,所以更新一般用_update

#post覆盖更新(删除原来的文档再插入)
POST /es_db/_doc/1
{
  "name":"张三2",
  "sex":1,
  "address":"广州天河公园",
  "remake":"java developer"
}

#put覆盖更新(删除原来的文档再插入)
PUT /es_db/_doc/1
{
  "name":"张三2",
  "sex":1,
  "address":"广州天河公园"
}

#局部更新文档(不会删除原来的属性,推荐用以下方法更新文档)
POST /es_db/_update/1
{
  "doc": {
    "age":27
  }
}

#查询后再更新
POST /es_db/_update_by_query
{
  "query":{
    "match":{
      "_id":1
    }
  },
  "script":{
    "source":"ctx._source.age=30"
  }
}

删除文档

#删除指定文档
DELETE /es_db/_doc/G17EmYgBvN_pzyBmoMoN

复杂查询

查询之前先创建索引并准备数据

创建blog索引并设置索引默认使用IK分词器的ik_max_word模式,不指定分词器会默认使用es内置的标准分词器(Standard Analyzer)进行分词,这个分词器在对中文分词时默认都是将中文的每个字当做一个词分,对中文不友好

##创建blog索引并设置索引默认使用IK分词器的ik_max_word模式,不指定分词器会默认使用es内置的标准分词器(Standard Analyzer)进行分词,这个分词器在对中文分词时默认都是将中文的每个字当做一个词分,对中文不友好
PUT /blog
{
  "settings": {
    "analysis": {
      "analyzer": {
        "default": {
          "tokenizer": "ik_max_word"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      },
      "age": {
        "type": "long"
      },
      "birthday": {
        "type": "date"
      },
      "desc": {
        "type": "text"
      },
      "tag": {
        "type": "keyword"
      }
    }
  }
}

##插入数据
PUT /blog/_doc/1
{
  "id":"1",
  "name" : "刘民锴",
  "age" : 18,
  "desc":"java是最好的语言",
  "tab":"java是最好的语言"
}

PUT /blog/_doc/2
{
  "id":"2",
  "name" : "马老师",
  "age" : 18,
  "desc":"c是最好的语言",
  "tab":"c是最好的语言"
}

PUT /blog/_doc/3
{
  "id":"3",
  "name" : "流柚",
  "age" : 3,
  "desc":"c++是最好的语言",
  "tab":"c++是最好的语言"
}

查询匹配(匹配、过滤、排序、分页)

match:匹配(会先将搜索词进行分词在去文档搜索)

_source:过滤字段

sort:排序

form、size 分页

## 查询匹配
  GET /blog/_doc/_search
  {
    "query":{
      "match":{
        "name":"流"
      }
    }
    ,
    "_source": ["name","desc"]
    ,
    "sort": [
      {
        "age": {
          "order": "asc"
        }
      }
    ]
    ,
    "from": 0
    ,
    "size": 1
  }

在这里插入图片描述

多条件查询(must、should、filter)

must 相当于 and
should 相当于 or
must_not 相当于 not (… and …)
filter 过滤

GET /blog/_doc/_search
{
  "query":{
    "bool": {
      "must": [
        {
          "match":{
            "age":3
          }
        },
        {
          "match": {
            "name": "流"
          }
        }
      ],
      "filter": {
        "range": {
          "age": {
            "gte": 1,
            "lte": 3
          }
        }
      }
    }
  }
}

在这里插入图片描述

match和term查询

match会对搜索词进行分词,将分词后的field去倒排索引寻找文档;
term不会对搜索词进行分词,用搜索词去倒排索引寻找文档;
match和term的区别在于是否拆解搜索词
数据类型text和keyword的区别也是是否对数据分词

##term不分词,用java去搜索
GET /blog/_doc/_search
{
  "query":{
    "term":{
      "desc":"java"
    }
  }
}

##match分词,会将“java是”分成“java”和“是”再去搜索
GET /blog/_doc/_search
{
  "query":{
    "match":{
      "desc":"java是"
    }
  }
}

wildcard查询

用wildcard模拟mysql中的like “%java%”

通配符 * 来表示任意多个字符
? 来表示任意一个字符

##wildcard 是一种查询方式,用于在文本字段中进行通配符匹配,用wildcard模拟mysql中的like "%java%"
GET /blog/_doc/_search
{
  "query": {
    "wildcard": {
      "tab": "*java*"
    }
  }
}

高亮查询

##高亮查询
GET blog/_doc/_search
{
  "query": {
    "match": {
      "name":"流"
    }
  }
  ,
  "highlight": {
    "fields": {
      "name": {}
    }
  }
}

##自定义前缀和后缀
GET blog/_doc/_search
{
  "query": {
    "match": {
      "name":"流"
    }
  }
  ,
  "highlight": {
    "pre_tags": "<p class='key' style='color:red'>",
    "post_tags": "</p>", 
    "fields": {
      "name": {}
    }
  }
}

在这里插入图片描述

SpringBoot整合ES

目录结构

在这里插入图片描述
ElasticSearchConfig配置类


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

@Configuration
public class ElasticSearchConfig {
    @Value("${es.ip}")
    private String esIp;
    @Value("${es.port}")
    private Integer port;

    // 注册 rest高级客户端
    @Bean
    public RestHighLevelClient restHighLevelClient() {
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost(esIp, port, "http")
                )
        );
        return client;
    }
}

User类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {

    private String name;
    private Integer age;
}

application.yml


server:
  port: 8056

es:
  ip: 192.168.100.110
  port: 9200

BootElasticsearchTrainingApplicationTests测试用例类

import com.alibaba.fastjson.JSON;
import com.honger1234.elasticsearchtraining.domain.User;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
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.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@SpringBootTest
class BootElasticsearchTrainingApplicationTests {

    @Autowired
    public RestHighLevelClient restHighLevelClient;

    // 测试索引的创建, Request PUT boot_index
    @Test
    public void testCreateIndex() throws IOException {
        CreateIndexRequest request = new CreateIndexRequest("boot_index");
        CreateIndexResponse response = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
        System.out.println(response.isAcknowledged());// 查看是否创建成功
        restHighLevelClient.close();
    }

    // 获取索引,并判断其是否存在
    @Test
    public void testIndexIsExists() throws IOException {
        GetIndexRequest request = new GetIndexRequest("boot_index");
        boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
        System.out.println(exists);// 索引是否存在
        restHighLevelClient.close();
    }

    // 测试索引删除
    @Test
    public void testDeleteIndex() throws IOException {
        DeleteIndexRequest request = new DeleteIndexRequest("boot_index");
        AcknowledgedResponse response = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
        System.out.println(response.isAcknowledged());// 是否删除成功
        restHighLevelClient.close();
    }

    // 添加文档(先创建一个User实体类,添加fastjson依赖)
    @Test
    public void testAddDocument() throws IOException {
        // 创建一个User对象
        User liuyou = new User("张三", 18);
        // 创建请求
        IndexRequest request = new IndexRequest("boot_index");
        // 制定规则 PUT /boot_index/_doc/1
        request.id("1");// 设置文档ID
        request.timeout(TimeValue.timeValueMillis(1000));// request.timeout("1s")
        // 将我们的数据放入请求中
        request.source(JSON.toJSONString(liuyou), XContentType.JSON);
        // 客户端发送请求,获取响应的结果
        IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
        System.out.println(response.status());// 获取建立索引的状态信息 CREATED
        System.out.println(response);// 查看返回内容 IndexResponse[index=liuyou_index,type=_doc,id=1,version=1,result=created,seqNo=0,primaryTerm=1,shards={"total":2,"successful":1,"failed":0}]
    }

    // 获得指定文档信息
    @Test
    public void testGetDocument() throws IOException {
        GetRequest request = new GetRequest("boot_index", "1");
        GetResponse response = restHighLevelClient.get(request, RequestOptions.DEFAULT);
        System.out.println(response.getSourceAsString());// 打印文档内容
        System.out.println(request);// 返回的全部内容和命令是一样的
        restHighLevelClient.close();
    }

    /**
     * 查询索引的全部文档
     *
     * @throws IOException
     */
    @Test
    public void testGetAllDocument() throws IOException {
        SearchRequest searchRequest = new SearchRequest("boot_index");
        SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        for (SearchHit hit : search.getHits().getHits()) {
            System.out.println(hit.getSourceAsString());
        }
        restHighLevelClient.close();
    }

    // 获取文档,判断是否存在 get /boot_index/_doc/1
    @Test
    public void testDocumentIsExists() throws IOException {
        GetRequest request = new GetRequest("boot_index", "1");
        // 不获取返回的 _source的上下文了
        request.fetchSourceContext(new FetchSourceContext(false));
        request.storedFields("_none_");
        boolean exists = restHighLevelClient.exists(request, RequestOptions.DEFAULT);
        System.out.println(exists);
    }

    // 更新文档内容
    @Test
    public void testUpdateDocument() throws IOException {
        UpdateRequest request = new UpdateRequest("boot_index", "1");
        User user = new User("李四", 11);
        request.doc(JSON.toJSONString(user), XContentType.JSON);
        UpdateResponse response = restHighLevelClient.update(request, RequestOptions.DEFAULT);
        System.out.println(response.status()); // OK
        restHighLevelClient.close();
    }

    // 删除文档
    @Test
    public void testDeleteDocument() throws IOException {
        DeleteRequest request = new DeleteRequest("boot_index", "1");
        request.timeout("1s");
        DeleteResponse response = restHighLevelClient.delete(request, RequestOptions.DEFAULT);
        System.out.println(response.status());// OK
    }


    /**
     * 批量添加文档
     *
     * @throws IOException
     */
    @Test
    public void testBatchAdd() throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        for (int i = 0; i < 3; i++) {
            IndexRequest request = new IndexRequest("boot_index");// 没有id会自动生成一个随机ID
            request.id(String.valueOf(i));
            request.source(JSON.toJSONString(new User("liu" + i, 15 + i)), XContentType.JSON);
            bulkRequest.add(request);
        }
        BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        System.out.println(bulkResponse.status());
        if (bulkResponse.hasFailures()) {
            // 处理批量添加失败的情况
        }
    }

    /**
     * 复杂查询
     * SearchRequest 搜索请求
     * SearchSourceBuilder 条件构造
     * HighlightBuilder 高亮
     * TermQueryBuilder 精确查询
     * MatchAllQueryBuilder
     * xxxQueryBuilder ...
     *
     * @throws IOException
     */
    @Test
    public void testSearch() throws IOException {
        // 1.创建查询请求对象
        SearchRequest searchRequest = new SearchRequest();
        // 2.构建搜索条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // (1)查询条件 使用QueryBuilders工具类创建
        // 精确查询
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "liu0");
        //        // 匹配查询
        //        MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
        // (2)其他<可有可无>:(可以参考 SearchSourceBuilder 的字段部分)
        // 设置高亮
        searchSourceBuilder.highlighter(new HighlightBuilder());
        //        // 分页
        //        searchSourceBuilder.from();
        //        searchSourceBuilder.size();
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        // (3)条件投入
        searchSourceBuilder.query(termQueryBuilder);
        // 3.添加条件到请求
        searchRequest.source(searchSourceBuilder);
        // 4.客户端查询请求
        SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        // 5.查看返回结果
        SearchHits hits = search.getHits();
        System.out.println(JSON.toJSONString(hits));
        System.out.println("=======================");
        for (SearchHit documentFields : hits.getHits()) {
            System.out.println(documentFields.getSourceAsMap());
        }
    }

}

pom.xml

<properties>
		<java.version>1.8</java.version>
		<!-- 统一版本 -->
		<elasticsearch.version>7.6.1</elasticsearch.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<!--导入elasticsearch-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
		</dependency>
		<!--导入fastjson、lombok-->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.70</version>
		</dependency>
		<!-- lombok需要安装插件 -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
	</dependencies>

参考链接

视频地址:https://www.bilibili.com/video/BV17a4y1x7zqp=10&vd_source=a3d625a64090fc4e2e34f1ae12c724f1
https://www.bilibili.com/video/BV1JY4y1Z714?p=18&vd_source=a3d625a64090fc4e2e34f1ae12c724f1
文档地址: https://www.kuangstudy.com/bbs/1354069127022583809#header23

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/649159.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是oa系统,什么是工单系统,有啥区别?

什么是oa系统&#xff0c;什么是工单系统&#xff0c;有啥区别&#xff1f; 一、OA系统与工单系统介绍 1、什么是OA系统 OA系统全称为Office Automation&#xff0c;即办公自动化系统。它是一种专门为企业和机构的日常办公工作提供服务的综合性软件平台&#xff0c;具有信息…

apple pencil有买的必要吗?平板电容笔推荐平价

在当今时代&#xff0c;高科技已经成为推动电子产品发展的重要动力之一。无论是在工作上&#xff0c;还是在学习上&#xff0c;iPad平板的使用都很方便。iPad将会和我们的生活联系在一起&#xff0c;不管是现在还是未来。iPad配上一个简单的电容笔&#xff0c;不仅可以提高工作…

分享11个常用的VSCode快捷键,让你编码更高效

因为频繁切换到鼠标可能会对你的手腕造成不利影响。 说实话&#xff0c;快速编程是我继续编码的原因之一&#xff08;开个玩笑&#xff0c;除非...&#xff09;。无论如何&#xff0c;我发现让我变得更快的关键是与鼠标分离。想一想&#xff0c;每次你需要移动鼠标时&#xff0…

STM32单片机(六)TIM定时器 -> 第四节:TIM输出比较练习(PWM驱动LED呼吸灯、PWM驱动舵机以及PWM驱动直流电机)

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

CSS查缺补漏之如何优雅解决margin垂直方向塌陷与合并问题?

一&#xff1a;父子元素之间margin垂直方向塌陷问题 在处理margin垂直方向问题时&#xff0c;经常会遇到在给子元素设置margin时&#xff0c;导致效果出现在了父元素上&#xff1b;如下代码所示&#xff1a; 代码原义是想实现三方面&#xff1a; ① 将box1的margin-top调为5…

从实现到原理,总结11种延迟任务的实现方式(上)

1 前言 延迟任务在我们日常生活中比较常见&#xff0c;比如订单支付超时取消订单功能&#xff0c;又比如自动确定收货的功能等等。 所以本篇文章就来从实现到原理来盘点延迟任务的11种实现方式&#xff0c;这些方式并没有绝对的好坏之分&#xff0c;只是适用场景的不大相同。…

高频前端React面试题汇总

近期整理了一下高频的前端面试题&#xff0c;分享给大家一起来学习。如有问题&#xff0c;欢迎指正&#xff01; 一、组件基础 1. React 事件机制 <div onClick{this.handleClick.bind(this)}>点我</div>React并不是将click事件绑定到了div的真实DOM上&#xff0…

ChatGPT+Mermaid自然语言流程图形化产出小试 | 京东云技术团队

ChatGPTMermaid语言实现技术概念可视化 本文旨在介绍如何使用ChatGPT和Mermaid语言生成流程图的技术。在现代软件开发中&#xff0c;流程图是一种重要的工具&#xff0c;用于可视化和呈现各种流程和结构。结合ChatGPT的自然语言处理能力和Mermaid的简单语法&#xff0c;可以轻…

【北邮国院大三下】Intellectual Property Law 知识产权基础 Week3

北邮国院大三电商在读&#xff0c;随课程进行整理知识点。仅整理PPT和相关法条中相对重要的知识点&#xff0c;个人认为相对不重要的细小的知识点不列在其中。如有错误请指出。转载请注明出处&#xff0c;祝您学习愉快。 如需要pdf格式的文件请私信联系或微信联系 本Week的主…

供应链|多期库存系统中具有销售损失的最优联合补货和转运策略

封面图来源&#xff1a; https://www.pexels.com/photo/aerial-shot-of-cargo-ship-on-sea-3840441/ 作者&#xff1a;Hossein Abouee-Mehrizi, Oded Berman, Shrutivandana Sharma 引用&#xff1a;Abouee-Mehrizi, H., Berman, O., & Sharma, S. (2015). Optimal joint r…

马原第三章复习2.生产力和生产关系

目录 社会基本矛盾和运动规律 社会基本矛盾和运动规律 这两个问题是最重点 生产力和生产关系 经济基础和上层建筑 生产力和生产关系 生产力是生产的能力 生产力是人类在实践中形成的改造自然使其适应自然的能力 生产力包含两个重要的要素:三要素 劳动

年化收益 21%:lightGBM的WFA滚动训练,使用qlib的alpha158因子集

原创文章第242篇&#xff0c;专注“个人成长与财富自由、世界运作的逻辑与投资"。 开始之前&#xff0c;先说说感受。 把整个框架与思路都在社群里开源出来&#xff0c;就是希望大家看懂思路&#xff0c;而不是拿一两个策略。说实话&#xff0c;投资哪有这种高确定性的“…

通义听悟上线,强大的视频会议和学习直播分析能力,人工智能如何改变我们的生活和工作方式?

什么是通义听悟 通义听悟已开启公测&#xff0c;公测期&#xff08;2023年6月1日至30日&#xff09;用户可体验所有AI功能&#xff0c;含全文概要、章节速览、发言总结等高阶AI功能&#xff0c;通过阿里云主账号登录。 官方给的应用场景&#xff1a; 1、实时会议记录&#x…

4.MySQL表的增删改查(进阶)

文章目录 &#x1f36f;1. 数据库约束&#x1f36f;&#x1f34e;1.1 约束类型&#x1f34e;&#x1f34f;1.2 NULL约束&#x1f34f;&#x1f34a;1.3 UNIQUE&#xff1a;唯一约束&#x1f34a;&#x1f34b;1.4 DEFAULT&#xff1a;默认值约束&#x1f34b;&#x1f352;1.5 …

MySQL数据库语言三、DCL语句

&#x1f618;作者简介&#xff1a;正在努力的99年公司职员。 &#x1f44a;宣言&#xff1a;人生就是B&#xff08;birth&#xff09;和D&#xff08;death&#xff09;之间的C&#xff08;choise&#xff09;&#xff0c;做好每一个选择。 &#x1f64f;创作不易&#xff0c;…

绩效管理的本质是激发员工,而不是扣工资!

绩效管理是企业管理中非常重要的一个环节&#xff0c;通过对员工表现进行评估和奖励&#xff0c;可以提高整个团队的士气和生产力。 然而&#xff0c;在实际操作中&#xff0c;有些企业却将绩效管理变成了惩罚员工的手段&#xff0c;甚至使用绩效扣除员工的薪水。这种做法不仅…

VALSE 2023:版面分析技术如何赋能生产生活?

目录 0 写在前面1 文档版面分析2 版面元素检测3 文档排版引擎总结 0 写在前面 VALSE年度研讨会旨在为中国青年学者在计算机视觉、图像处理、模式识别与机器学习研究领域提供一个具有深度的学术交流平台。VALSE秉持理性批判、勇于探索、实证和创新等科学精神&#xff0c;倡导自…

光伏电池建模及温度光照的影响曲线

光伏电池建模及温度光照的影响MATLAB程序及仿真资源-CSDN文库https://download.csdn.net/download/weixin_56691527/87910193模型介绍&#xff1a; 需要MATLAB2018B及以上的版本&#xff01;&#xff01; 首先根据根据环境修正公式搭建光伏电池仿真模型&#xff1a; 温度变化…

传统机器学习算法解析(opencv实现)

前言 文本主要解析在传统机器学习当中一些小的算法与思想&#xff0c;只是传统机器学习算法当中的一小部分&#xff0c;更多传统机器学习算法可参考我的另外几篇博客 链接1: PCA主成分分析 链接2: Canny边缘检测算法 链接3: K-Means聚类算法 链接4: SIFT算法分析 1. opencv …

MMDeploy安装和pth转ONNX

参考&#xff1a; https://github.com/open-mmlab/mmdeploy/blob/main/README_zh-CN.md MMDeploy安装指导 MMDeploy 是 OpenMMLab 模型部署工具箱&#xff0c;为各算法库提供统一的部署体验。基于 MMDeploy&#xff0c;开发者可以轻松从训练 repo 生成指定硬件所需 SDK&#…