Elasticsearch先容及利用

[复制链接]
发表于 2025-11-10 11:44:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
Elasticsearch 是一款基于 Lucene 库构建的开源、分布式、RESTful 风格的搜刮引擎和分析引擎,具有强盛的全文搜刮、数据分析、呆板学习等功能,广泛应用于日记分析、及时数据分析、全文检索等场景。
焦点概念

   

  • 索引(Index):雷同于传统数据库中的数据库,是存储数据的逻辑容器。一个索引可以包罗多个范例的数据,每个索引都有一个唯一的名称用于标识。
  • 范例(Type):在早期版本中,一个索引可以有多个范例,用来区分差别范例的数据,但在 7.x 及以上版本中,一个索引只能有一个范例,且默认范例为“_doc”。
  • 文档(Document):是 Elasticsearch 中存储和检索的根本数据单元,以 JSON 格式表现。每个文档都有一个唯一的 ID,用于在索引中定位和利用文档。
  • 字段(Field):是文档中的一个属性或键值对,用于存储详细的数据内容,如姓名、年事、代价等。字段有差别的数据范例,如文本、数字、日期等,差别的数据范例决定了字段的存储和检索方式。
紧张特点

   

  • 高性能全文搜刮:基于 Lucene 的倒排索引技能,可以或许快速地对文本数据举行全文搜刮。它会将文本数据拆分成单词或词汇,创建索引,当举行搜刮时,通过查找索引快速定位到包罗搜刮关键词的文档,大大进步了搜刮服从。
  • 分布式架构:可以摆设在多个节点上,形成一个分布式集群。数据会被主动分片存储在差别的节点上,当一个节点出现标题时,其他节点可以继承提供服务,包管了体系的高可用性和数据的可靠性。同时,分布式架构也使得 Elasticsearch 可以或许处理处罚海量的数据和高并发的哀求。
  • 易于扩展:随着数据量和访问量的增长,可以通过简单地增长节点来水平扩展集群。新参加的节点会主动加入数据的存储和查询工作,无需对现有体系举行复杂的改造,可以或许机动地应对业务的增长。
  • RESTful API:提供了基于 HTTP 协议的 RESTful 风格的 API 接口,方便开辟者利用各种编程语言举行集成和开辟。通过简单的 HTTP 哀求,就可以完成数据的增编削查、索引管理、查询分析等各种利用,低沉了开辟难度和本钱。
  • 多租户支持:在 Elasticsearch 集群中,可以创建多个索引,每个索引可以视为一个独立的“租户”,差别租户之间的数据相互隔离。这使得 Elasticsearch 可以或许在一个集群中同时为多个应用步调或用户提供服务,进步了资源利用率。
  • 强盛的聚合分析功能:除了根本的搜刮功能,还提供了丰富的聚合分析功能,如统计、分组、排序、时间序列分析等。可以对搜刮效果举行进一步的数据发掘和分析,资助用户快速获取数据的统计信息和趋势,为决定提供支持。








常见应用场景

   

  • 日记分析:可以或许高效地网络、存储和分析各种日记数据,如服务器日记、应用步调日记、网络装备日记等。通过对日记数据的搜刮、过滤、聚合分析,可以快速定位体系故障、性能瓶颈、安全标题等,为运维职员提供有力的工具。
  • 及时数据分析:实用于必要及时处理处罚和分析大量数据的场景,如金融生意业务监控监控、交际媒体数据监测、物联网物联网装备数据处理处罚等。Elasticsearch 可以及时地吸收数据,快速地举行查询和分析,及时发现非常情况并做出相应。
  • 全文检索:为各种必要全文检索功能的应用步调提供支持,如电子商务网站的商品搜刮、知识管理体系的内容检索、消息网站的消息搜刮等。可以或许根据用户的输入关键词,快速地在海量文本数据中找到匹配的效果,并按照相干性举行排序,提升用户体验。
  • 呆板学习:团结 Elasticsearch 的呆板学习功能,可以对数据举行主动分析和建模,实现非常检测、推测分析等高级功能。比方,在网络安全范畴,通过呆板学习算法对网络流量数据举行分析,主动辨认埋伏的攻击举动;在电商范畴,推测用户的购买举动和需求。
架构组件

   

  • 节点(Node):是 Elasticsearch 集群中的一个服务器实例,负担着数据存储、查询处理处罚、集群管理等任务。节点之间通过网络举行通讯和协作,共同构成一个完备的 Elasticsearch 集群。
  • 集群(Cluster):由一个或多个节点构成,通过设置集群名称来标识。集群负责管理节点、分配分片、处理处罚哀求等,包管数据的同等性和高可用性。集群中的主节点(Master Node)负责集群级别的利用,如创建索引、分配分片、节点发现等,数据节点(Data Node)紧张负责存储数据和实行查询利用。
  • 分片(Shard):为了进步数据的存储本事和查询性能,索引会被分割成多个分片,每个分片是一个独立的 Lucene 索引。分片可以分布在差别的节点上,当举行查询时,查询哀求会被分发到各个分片上并行实行,然后将效果汇总返回。分片的数目在索引创建时确定,可以根据数据量和查询需求举行公道设置。
  • 副本(Replica):是分片的副本,用于进步数据的可靠性和查询性能。当一个分片出现故障时,副本可以继承其查询哀求,包管服务的可用性。同时,副本也可以分担查询负载,进步查询的并发处理处罚本事。副本的数目可以根据集群的节点数目和可靠性要求举行设置。
数据写入与查询流程

   

  • 数据写入流程:

    • 客户端发送写入哀求:用户或应用步调通过 Elasticsearch 的 RESTful API 向集群发送数据写入哀求,哀求中包罗要写入的索引名称、文档数据等信息。
    • 主节点路由哀求:主节点吸收到哀求后,根据索引的分片计谋,将写入哀求路由到对应的主分片地点的节点。
    • 主分片写入数据:主分片节点吸收到哀求后,将数据写入本地的分片中,并记载利用日记。写入乐成后,会将利用日记发送给对应的副天职片节点。
    • 副天职片同步数据:副天职片节点吸收到利用日记后,会根据日记内容将数据同步到本地的副天职片中。当全部副天职片都乐成同步数据后,主分片节点会向客户端返回写入乐成的相应。

  • 数据查询流程:

    • 客户端发送查询哀求:用户或应用步调通过 RESTful API 向集群发送查询哀求,哀求中包罗查询条件、索引名称等信息。
    • 主节点分发查询哀求:主节点吸收到查询哀求后,根据索引的分片分布情况,将查询哀求分发到全部相干的分片地点的节点。
    • 分片节点实行查询:各个分片节点吸收到查询哀求后,在本地的分片中实行查询利用,根据查询条件检索匹配的文档,并将查询效果返回给主节点。
    • 主节点汇总效果:主节点吸收到各个分片节点返回的查询效果后,对效果举行汇总和排序等处理处罚,然后将终极的查询效果返回给客户端。

Elasticsearch根本概念

   Index:索引(index),就是文档的聚集,雷同数据库的表(table)
  Document:文档(Document),就是一条条的数据,雷同数据库中的行(Row),文档都是JSON格式
  Field:字段(Field),就是JSON文档中的字段,雷同数据库中的列(Column)
  Mapping:Mapping(映射)是索引中文档的束缚,比方字段范例束缚。雷同数据库的表布局(Schema)
  DSL:DSL是elasticsearch提供的JSON风格的哀求语句,用来利用elasticsearch,实现CRUD
  倒排索引

正向索引


  • 文档 ID:用于唯一标识每个文档,雷同数据库表中的主键,有了它就能精准定位到特定的某一文档。
  • 索引项:跟在文档 ID 反面,包罗了文档中的各类关键元素,好比文本里的词汇、数据记载的属性值等,有的还会附上这些元素在文档中的详细位置信息。
倒排索引


  • 文档(Document):用来搜刮的数据,此中的每一条数据就是一个文档。比方一个网页、一个商品信息。
  • 词条(Term):对文档数据或用户搜刮数据,利用某种算法分词,得到的具备寄义的词语就是词条。比方:我是中国人,就可以分为:我、是、中国人、中国、国人如许的几个词条。
对比
正向索引的表布局
  id(索引)
  title
  price
  1
  小米手机
  3499
  2
  华为手机
  4999
  3
  华为小米充电器
  49
  4
  小米手环
  49
搜刮流程:


  • 1)如查抄到搜刮条件为like '%手机%',必要找到title中包罗手机的数据
  • 2)逐条遍历每行数据(每个叶子节点),好比第1次拿到id为1的数据
  • 3)判定数据中的title字段值是否符合条件
  • 4)如果符合则放入效果集,不符合则扬弃
  • 5)回到步调1
倒排索引的表布局
  词条(索引)
  文档id
  小米
  1,3,4
  手机
  1,2
  华为
  2,3
  充电器
  3
  手环
  4
 搜刮流程:
1)如用户输入条件"华为手机"举行搜刮。
2)对用户输入条件分词,得到词条:华为、手机。
3)拿着词条在倒排索引中查找(由于词条有索引,查询服从很高),即可得到包罗词条的文档id:1、2、3。
4)拿着文档id到正向索引中查找详细文档即可(由于id也有索引,查询服从也很高)。
正向索引:


  • 长处:

    • 可以给多个字段创建索引
    • 根据索引字段搜刮、排序速率非常快

  • 缺点:

    • 根据非索引字段,大概索引字段中的部门词条查找时,只能全表扫描。

倒排索引:


  • 长处:

    • 根据词条搜刮、暗昧搜刮时,速率非常快

  • 缺点:

    • 只能给词条创建索引,而不是字段
    • 无法根据字段做排序

安装Elasticsearch

1.利用docker安装单机版的Elasticsearch
  1. docker run -d \
  2.   --name es \
  3.   -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
  4.   -e "discovery.type=single-node" \
  5.   -v es-data:/usr/share/elasticsearch/data \
  6.   -v es-plugins:/usr/share/elasticsearch/plugins \
  7.   --privileged \
  8.   --network es-net \
  9.   -p 9200:9200 \
  10.   -p 9300:9300 \
  11.   --restart=always \
  12.   elasticsearch:7.12.1
复制代码
代码解读:
-d:让容器在配景运行
--name:指定创建的容器名称
-e:设置容器内的情况变量
-v:将容器内的目次挂载到外部的卷上
--privileged:以特权模式运行容器
--network:将容器毗连到名为 es-net 的 Docker 网络,在我们搭建服务器的时间可以创建一个docker网络,将要相互通讯的放在这一个网络内里。注意:这里必要先用docker network create创建一个docker网络这里才气指定
-p:将容器的端口映射到主机的端口
--restart=always:设置容器自启动
 elasticsearch:7.12.1:要运行的 Docker 镜像名称和标签,如果我们指定这个镜像本地没有这个版本就会举行下载。注意:这里我们采取的是elasticsearch的7.12.1版本,由于8以上版本的JavaAPI变革很大,在企业中应用并不广泛,企业中应用较多的还是8以下的版本。
2.防火墙开放端口
  1. #1.开放es端口
  2. firewall-cmd --zone=public --add-port=9200/tcp --add-port=9300/tcp --permanent
  3. #2.重新加载防火墙配置
  4. firewall-cmd --reload
复制代码
也可以关闭防火墙
  1. systemctl stop firewalld
复制代码
3.访问9200端口验证es是否启动乐成
地点格式:主机IP:9200

IK分词器

Elasticsearch的关键就是倒排索引,而倒排索引依赖于对文档内容的分词,而分词则必要高效、精准的分词算法,IK分词器就是如许一个中文分词算法。
安装

方法一:在线安装
  1. docker exec -it es ./bin/elasticsearch-plugin  install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip
复制代码
重启es容器
  1. docker restart es
复制代码
方法二:离线安装
起首,查察之前安装的es容器的plugins数据卷目次:
  1. docker volume inspect es-plugins
复制代码
效果如下: 

进入/var/lib/docker/volumes/es-plugins/_data目次,将我们本地的ik上传到这个目次下

 重启es容器
  1. docker restart es
复制代码
利用

IK分词器包罗两种模式:
ik_smart:智能语义切分
示例:
  1. POST /_analyze
  2. {
  3.   "analyzer": "ik_smart",
  4.   "text": "我是一个程序员"
  5. }
复制代码
效果:
  1. {
  2.   "tokens" : [
  3.     {
  4.       "token" : "我",
  5.       "start_offset" : 0,
  6.       "end_offset" : 1,
  7.       "type" : "CN_CHAR",
  8.       "position" : 0
  9.     },
  10.     {
  11.       "token" : "是",
  12.       "start_offset" : 1,
  13.       "end_offset" : 2,
  14.       "type" : "CN_CHAR",
  15.       "position" : 1
  16.     },
  17.     {
  18.       "token" : "一个",
  19.       "start_offset" : 2,
  20.       "end_offset" : 4,
  21.       "type" : "CN_WORD",
  22.       "position" : 2
  23.     },
  24.     {
  25.       "token" : "程序员",
  26.       "start_offset" : 4,
  27.       "end_offset" : 7,
  28.       "type" : "CN_WORD",
  29.       "position" : 3
  30.     }
  31.   ]
  32. }
复制代码
ik_max_word:最细粒度切分
示例:
  1. POST /_analyze
  2. {
  3.   "analyzer": "ik_max_word",
  4.   "text": "我是一个程序员"
  5. }
复制代码
效果: 
  1. {
  2.   "tokens" : [
  3.     {
  4.       "token" : "我",
  5.       "start_offset" : 0,
  6.       "end_offset" : 1,
  7.       "type" : "CN_CHAR",
  8.       "position" : 0
  9.     },
  10.     {
  11.       "token" : "是",
  12.       "start_offset" : 1,
  13.       "end_offset" : 2,
  14.       "type" : "CN_CHAR",
  15.       "position" : 1
  16.     },
  17.     {
  18.       "token" : "一个",
  19.       "start_offset" : 2,
  20.       "end_offset" : 4,
  21.       "type" : "CN_WORD",
  22.       "position" : 2
  23.     },
  24.     {
  25.       "token" : "一",
  26.       "start_offset" : 2,
  27.       "end_offset" : 3,
  28.       "type" : "TYPE_CNUM",
  29.       "position" : 3
  30.     },
  31.     {
  32.       "token" : "个",
  33.       "start_offset" : 3,
  34.       "end_offset" : 4,
  35.       "type" : "COUNT",
  36.       "position" : 4
  37.     },
  38.     {
  39.       "token" : "程序员",
  40.       "start_offset" : 4,
  41.       "end_offset" : 7,
  42.       "type" : "CN_WORD",
  43.       "position" : 5
  44.     },
  45.     {
  46.       "token" : "程序",
  47.       "start_offset" : 4,
  48.       "end_offset" : 6,
  49.       "type" : "CN_WORD",
  50.       "position" : 6
  51.     },
  52.     {
  53.       "token" : "员",
  54.       "start_offset" : 6,
  55.       "end_offset" : 7,
  56.       "type" : "CN_CHAR",
  57.       "position" : 7
  58.     }
  59.   ]
  60. }
复制代码
 拓展辞书

随着互联网的发展,“造词运动”也越发的频仍。出现了很多新的词语,在原有的词汇列表中并不存在,如:“逆天、依托答辩、我了个豆”
  1. POST /_analyze
  2. {
  3.   "analyzer": "ik_max_word",
  4.   "text": "逆天、依托答辩、我了个豆"
  5. }
复制代码
效果:
  1. {
  2.   "tokens" : [
  3.     {
  4.       "token" : "逆",
  5.       "start_offset" : 0,
  6.       "end_offset" : 1,
  7.       "type" : "CN_CHAR",
  8.       "position" : 0
  9.     },
  10.     {
  11.       "token" : "天",
  12.       "start_offset" : 1,
  13.       "end_offset" : 2,
  14.       "type" : "CN_CHAR",
  15.       "position" : 1
  16.     },
  17.     {
  18.       "token" : "依托",
  19.       "start_offset" : 3,
  20.       "end_offset" : 5,
  21.       "type" : "CN_WORD",
  22.       "position" : 2
  23.     },
  24.     {
  25.       "token" : "答辩",
  26.       "start_offset" : 5,
  27.       "end_offset" : 7,
  28.       "type" : "CN_WORD",
  29.       "position" : 3
  30.     },
  31.     {
  32.       "token" : "我",
  33.       "start_offset" : 8,
  34.       "end_offset" : 9,
  35.       "type" : "CN_CHAR",
  36.       "position" : 4
  37.     },
  38.     {
  39.       "token" : "了",
  40.       "start_offset" : 9,
  41.       "end_offset" : 10,
  42.       "type" : "CN_CHAR",
  43.       "position" : 5
  44.     },
  45.     {
  46.       "token" : "个",
  47.       "start_offset" : 10,
  48.       "end_offset" : 11,
  49.       "type" : "CN_CHAR",
  50.       "position" : 6
  51.     },
  52.     {
  53.       "token" : "豆",
  54.       "start_offset" : 11,
  55.       "end_offset" : 12,
  56.       "type" : "CN_CHAR",
  57.       "position" : 7
  58.     }
  59.   ]
  60. }
复制代码
可以看到,逆天和我了个豆都无法正确分词。
以是要想正确分词,IK分词器的词库也必要不绝的更新,IK分词器提供了扩展词汇的功能。
1)打开IK分词器config目次:

注意:如果采取在线安装的通过,默认是没有config目次的,可以去网上找一些词库,让后创建一个config文件目次放在config目次下
2)在IKAnalyzer.cfg.xml设置文件内容添加:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
  3. <properties>
  4.         <comment>IK Analyzer 扩展配置</comment>
  5.         <!--可以在这里配置自己的扩展字典 -->
  6.         <entry key="ext_dict">ext.dic</entry>
  7. </properties>
复制代码
3)新建ext.dic文件,用记事本大概其他编辑器打开ext.dic文件,然后添加本身想要的词语即可

4)重启elasticsearch
  1. docker restart es
  2. # 查看 日志日志
  3. docker logs -f elasticsearch
复制代码
5.重启之后再次实行之前的下令,可以正确分词了
  1. {
  2.   "tokens" : [
  3.     {
  4.       "token" : "逆天",
  5.       "start_offset" : 0,
  6.       "end_offset" : 2,
  7.       "type" : "CN_WORD",
  8.       "position" : 0
  9.     },
  10.     {
  11.       "token" : "依托答辩",
  12.       "start_offset" : 3,
  13.       "end_offset" : 7,
  14.       "type" : "CN_WORD",
  15.       "position" : 1
  16.     },
  17.     {
  18.       "token" : "依托",
  19.       "start_offset" : 3,
  20.       "end_offset" : 5,
  21.       "type" : "CN_WORD",
  22.       "position" : 2
  23.     },
  24.     {
  25.       "token" : "答辩",
  26.       "start_offset" : 5,
  27.       "end_offset" : 7,
  28.       "type" : "CN_WORD",
  29.       "position" : 3
  30.     },
  31.     {
  32.       "token" : "我了个豆",
  33.       "start_offset" : 8,
  34.       "end_offset" : 12,
  35.       "type" : "CN_WORD",
  36.       "position" : 4
  37.     }
  38.   ]
  39. }
复制代码
还可以在IKAnalyzer.cfg.xml加上如下设置:实现更多功能
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
  3. <properties>
  4.         <comment>IK Analyzer 扩展配置</comment>
  5.         <!--用户可以在这里配置自己的扩展字典 -->
  6.         <entry key="ext_dict">ext.dic</entry>
  7.          <!--用户可以在这里配置自己的扩展停止词字典-->
  8.         <entry key="ext_stopwords">stopword.dic</entry>
  9.         <!--用户可以在这里配置远程扩展字典 -->
  10.         <!-- <entry key="remote_ext_dict">words_location</entry> -->
  11.         <!--用户可以在这里配置远程扩展停止词字典-->
  12.         <!-- <entry key="remote_ext_stopwords">words_location</entry> -->
  13. </properties>
复制代码
RESTAPI利用

ES官方提供了各种差别语言的客户端,用来利用ES。这些客户端的本质就是组装DSL语句,通过http哀求发送给ES。
官方文档地点:
Elasticsearch Clients | Elastic
由于ES如今最新版本是8.8,提供了全新版本的客户端,老版本的客户端已经被标记为过期。而我们采取的是7.12版本,因此只能利用老版本客户端:

然后选择7.12版本,HighLevelRestClient版本:


1.引入es的RestHighLevelClient依赖:
  1. <dependency>
  2.     <groupId>org.elasticsearch.client</groupId>
  3.     <artifactId>elasticsearch-rest-high-level-client</artifactId>
  4.     <version>7.12.1</version>
  5. </dependency>
复制代码
2.初始化RestHighLevelClient:
  1. public class IndexTest {
  2.     private RestHighLevelClient client;
  3.     @BeforeEach
  4.     void setUp() {
  5.         this.client = new RestHighLevelClient(RestClient.builder(
  6.                 HttpHost.create("http://192.168.181.32:9200")//es服务ip地址:端口号
  7.         ));
  8.     }
  9.     @Test
  10.     void testConnect() {
  11.         System.out.println(client);//执行不好错就行了
  12.     }
  13.     @AfterEach
  14.     void tearDown() throws IOException {
  15.         this.client.close();
  16.     }
  17. }
复制代码
3.索引库相干利用:
  1. public class ElasticIndexTest {
  2.   private static final String MAPPING_TEMPLATE = """
  3.     {
  4.       "mappings": {
  5.         "properties": {
  6.           "id": {
  7.             "type": "keyword"
  8.           },
  9.           "name": {
  10.             "type": "text",
  11.             "analyzer": "ik_smart"
  12.           },
  13.           "price": {
  14.             "type": "integer"
  15.           },
  16.           "image": {
  17.             "type": "keyword",
  18.             "index": false
  19.           },
  20.           "category": {
  21.             "type": "keyword"
  22.           },
  23.           "brand": {
  24.             "type": "keyword"
  25.           },
  26.           "sold": {
  27.             "type": "integer"
  28.           },
  29.           "commentCount": {
  30.             "type": "integer",
  31.             "index": false
  32.           },
  33.           "isAD": {
  34.             "type": "boolean"
  35.           },
  36.           "updateTime": {
  37.             "type": "date"
  38.           }
  39.         }
  40.       }
  41.     }
  42.     """;//JDK15新特性:三引号
  43.   private RestHighLevelClient client;
  44. //创建
  45.   @Test
  46.   void testCreateIndex() throws IOException {
  47.     //准备request对象
  48.     CreateIndexRequest request = new CreateIndexRequest("items");
  49.     //准备请求参数
  50.     request.source(MAPPING_TEMPLATE, XContentType.JSON);
  51.     //发送请求
  52.     client.indices().create(request, RequestOptions.DEFAULT);
  53.   }
  54. //判断是否存在
  55.   @Test
  56.   void testExistsndex() throws IOException {
  57.     //准备request对象
  58.     GetIndexRequest request = new GetIndexRequest("items");
  59.     //发送请求
  60.     boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
  61.     System.out.println("exists = " + exists);
  62.   }
  63. //删除
  64.   @Test
  65.   void testDeleteIndex() throws IOException {
  66.     //准备request对象
  67.     DeleteIndexRequest request = new DeleteIndexRequest("items");
  68.     //发送请求
  69.     client.indices().delete(request, RequestOptions.DEFAULT);
  70.   }
  71.   @BeforeEach
  72.   void setUp() {
  73.     client = new RestHighLevelClient(RestClient.builder(
  74.       HttpHost.create("http://192.168.181.32:9200")
  75.     ));
  76.   }
  77.   @AfterEach
  78.   void tearDown() throws IOException {
  79.     if (client != null) {
  80.       client.close();
  81.     }
  82.   }
  83. }
复制代码
4.文档相干利用:
  1. package com.hmall.item.es;
  2. import cn.hutool.core.bean.BeanUtil;
  3. import cn.hutool.json.JSONUtil;
  4. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  5. import com.hmall.item.domain.po.Item;
  6. import com.hmall.item.domain.po.ItemDoc;
  7. import com.hmall.item.service.IItemService;
  8. import org.apache.http.HttpHost;
  9. import org.elasticsearch.action.bulk.BulkRequest;
  10. import org.elasticsearch.action.delete.DeleteRequest;
  11. import org.elasticsearch.action.get.GetRequest;
  12. import org.elasticsearch.action.get.GetResponse;
  13. import org.elasticsearch.action.index.IndexRequest;
  14. import org.elasticsearch.action.update.UpdateRequest;
  15. import org.elasticsearch.client.RequestOptions;
  16. import org.elasticsearch.client.RestClient;
  17. import org.elasticsearch.client.RestHighLevelClient;
  18. import org.elasticsearch.common.xcontent.XContentType;
  19. import org.junit.jupiter.api.AfterEach;
  20. import org.junit.jupiter.api.BeforeEach;
  21. import org.junit.jupiter.api.Test;
  22. import org.springframework.beans.factory.annotation.Autowired;
  23. import org.springframework.boot.test.context.SpringBootTest;
  24. import java.io.IOException;
  25. import java.util.List;
  26. @SpringBootTest(properties = "spring.profiles.active=local")
  27. public class ElasticDocumentTest {
  28.   private RestHighLevelClient client;
  29.   @Autowired
  30.   private IItemService itemService;
  31.   @BeforeEach
  32.   void setUp() {
  33.     client = new RestHighLevelClient(RestClient.builder(
  34.       HttpHost.create("http://192.168.181.32:9200")
  35.     ));
  36.   }
  37.   //创建文档
  38.   @Test
  39.   void createDoc() throws IOException {
  40.     //准备文档数据
  41.     //1.查询数据
  42.     Item item = itemService.getById(577967L);
  43.     //2.把数据库数据转成文档数据
  44.     ItemDoc itemDoc = BeanUtil.copyProperties(item, ItemDoc.class);
  45.     //准备request对象
  46.     IndexRequest request = new IndexRequest("items").id(itemDoc.getId());
  47.     //构建请求参数
  48.     request.source(JSONUtil.toJsonStr(itemDoc), XContentType.JSON);
  49.     //发送请求
  50.     client.index(request, RequestOptions.DEFAULT);
  51.   }
  52.   //获取文档数据
  53.   @Test
  54.   void testGetDoc() throws IOException {
  55.     //准备request对象
  56.     GetRequest request = new GetRequest("items", "577967");
  57.     //发送请求
  58.     GetResponse response = client.get(request, RequestOptions.DEFAULT);
  59.     //获取响应结果中的source
  60.     String json = response.getSourceAsString();
  61.     //转成java对象
  62.     ItemDoc itemDoc = JSONUtil.toBean(json, ItemDoc.class);
  63.     System.out.println("itemDoc = " + itemDoc);
  64.   }
  65.   //删除文档
  66.   @Test
  67.   void testDelDoc() throws IOException {
  68.     //准备request对象
  69.     DeleteRequest request = new DeleteRequest("items", "577967");
  70.     //发送请求
  71.     client.delete(request, RequestOptions.DEFAULT);
  72.   }
  73.   //修改文档数据
  74.   @Test
  75.   void testUpdateDoc() throws IOException {
  76.     //准备request对象
  77.     UpdateRequest request = new UpdateRequest("items", "577967");
  78.     request.doc("price", 29900);
  79.     //发送请求
  80.     client.update(request, RequestOptions.DEFAULT);
  81.   }
  82.   //批量操作文档:新增
  83.   @Test
  84.   void testBulkDoc() throws IOException {
  85.     int pageNo = 1, pageSize = 500;
  86.     while (true) {
  87.       Page<Item> page = itemService.lambdaQuery().eq(Item::getStatus, 1).page(Page.of(pageNo, pageSize));
  88.       List<Item> records = page.getRecords();
  89.       if (records == null || records.isEmpty()) {
  90.         return;
  91.       }
  92.       //准备BulkRequest对象
  93.       BulkRequest request = new BulkRequest();
  94.       for (Item item : records) {
  95.         //添加批量提交的请求
  96.         request
  97.           .add(new IndexRequest("items")
  98.             .id(item.getId().toString())
  99.             .source(JSONUtil.toJsonStr(BeanUtil.copyProperties(item, ItemDoc.class)), XContentType.JSON));
  100.       }
  101.       //提交请求
  102.       client.bulk(request, RequestOptions.DEFAULT);
  103.       pageNo++;
  104.     }
  105.   }
  106.   @AfterEach
  107.   void tearDown() throws IOException {
  108.     if (client != null) {
  109.       client.close();
  110.     }
  111.   }
  112. }
复制代码
5.查询数据相干利用:
  1. public class ElasticSearchTest {
  2.   private RestHighLevelClient client;
  3.   private static void parseResponseResult(SearchResponse response) {
  4.     //得到命中的数据
  5.     SearchHits hits = response.getHits();
  6.     long total = hits.getTotalHits().value;
  7.     System.out.println("total = " + total);
  8.     for (SearchHit hit : hits) {
  9.       //解析数据
  10.       String json = hit.getSourceAsString();
  11.       //封装itemDoc
  12.       ItemDoc doc = JSONUtil.toBean(json, ItemDoc.class);
  13.       //处理高亮字段
  14.       Map<String, HighlightField> hfs = hit.getHighlightFields();
  15.       if (hfs != null && !hfs.isEmpty()) {
  16.         //更具高亮字段名获取高亮结果
  17.         HighlightField hf = hfs.get("name");
  18.         //用获取到的高亮值覆盖原来非高亮的字段值
  19.         String hfName = hf.getFragments()[0].toString();
  20.         doc.setName(hfName);
  21.       }
  22.       System.out.println("doc = " + doc);
  23.     }
  24.   }
  25.   //查询全部
  26.   @Test
  27.   void testMatchAll() throws IOException {
  28.     //创建
  29.     SearchRequest request = new SearchRequest("items");
  30.     //组织DSL查询参数
  31.     request.source().query(QueryBuilders.matchAllQuery());
  32.     //发送请求
  33.     SearchResponse response = client.search(request, RequestOptions.DEFAULT);
  34.     //解析结果
  35.     parseResponseResult(response);
  36.   }
  37.   //根据条件查询:复合查询
  38.   @Test
  39.   void testSearch() throws IOException {
  40.     //创建
  41.     SearchRequest request = new SearchRequest("items");
  42.     //组织DSL查询参数
  43.     request.source().query(
  44.       QueryBuilders.boolQuery()
  45.         .must(QueryBuilders.matchQuery("name", "脱脂牛奶"))
  46.         .filter(QueryBuilders.termQuery("brand", "德亚"))
  47.         .filter(QueryBuilders.rangeQuery("price").lt(30000))
  48.     );
  49.     //发送请求
  50.     SearchResponse response = client.search(request, RequestOptions.DEFAULT);
  51.     //解析结果
  52.     parseResponseResult(response);
  53.   }
  54.   
  55.   //分页排序
  56.   @Test
  57.   void testPageAndSort() throws IOException {
  58.     int pageNo = 1, pageSize = 5;
  59.     // 1.创建Request
  60.     SearchRequest request = new SearchRequest("items");
  61.     // 2.组织请求参数
  62.     // 2.1.搜索条件参数
  63.     request.source().query(QueryBuilders.matchQuery("name", "脱脂牛奶"));
  64.     // 2.2.排序参数
  65.     request.source().sort("price", SortOrder.ASC);
  66.     // 2.3.分页参数
  67.     request.source().from((pageNo - 1) * pageSize).size(pageSize);
  68.     // 3.发送请求
  69.     SearchResponse response = client.search(request, RequestOptions.DEFAULT);
  70.     // 4.解析响应
  71.     parseResponseResult(response);
  72.   }
  73.   //根据条件获取高亮数据
  74.   @Test
  75.   void testHighlight() throws IOException {
  76.     //创建
  77.     SearchRequest request = new SearchRequest("items");
  78.     //组织DSL查询参数
  79.     //query条件
  80.     request.source().query(QueryBuilders.matchQuery("name", "脱脂牛奶"));
  81.     //高亮条件
  82.     request.source().highlighter(SearchSourceBuilder.highlight().field("name"));
  83.     //发送请求
  84.     SearchResponse response = client.search(request, RequestOptions.DEFAULT);
  85.     //解析结果
  86.     parseResponseResult(response);
  87.   }
  88.   //数据聚合
  89.   @Test
  90.   void testAgg() throws IOException {
  91.     //创建
  92.     SearchRequest request = new SearchRequest("items");
  93.     //组织DSL查询参数
  94.     //query条件
  95.     request.source().size(0);
  96.     //聚合条件
  97.     String brandAggName = "brandAgg";
  98.     request.source().aggregation(
  99.       AggregationBuilders.terms(brandAggName).field("brand").size(10)
  100.     );
  101.     //发送请求
  102.     SearchResponse response = client.search(request, RequestOptions.DEFAULT);
  103.     //解析结果
  104.     Aggregations aggregations = response.getAggregations();
  105.     //根据聚合名称获取聚合
  106.     Terms aggTerms = aggregations.get(brandAggName);
  107.     //获取buckets
  108.     List<? extends Terms.Bucket> buckets = aggTerms.getBuckets();
  109.     //遍历每一个bucket
  110.     for (Terms.Bucket bucket : buckets) {
  111.       System.out.println("brand:"+bucket.getKeyAsString());
  112.       System.out.println("count:"+bucket.getDocCount());
  113.     }
  114.   }
  115.   @BeforeEach
  116.   void setUp() {
  117.     client = new RestHighLevelClient(RestClient.builder(
  118.       HttpHost.create("http://192.168.181.32:9200")
  119.     ));
  120.   }
  121.   @AfterEach
  122.   void tearDown() throws IOException {
  123.     if (client != null) {
  124.       client.close();
  125.     }
  126.   }
  127. }
复制代码

回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表