[微服务]elasticsearc客服端操作

ops/2024/12/28 14:11:18/

客户端初始化

Elasticsearch目前最新版本是8.0,其java客户端有很大变化。不过大多数企业使用的还是8以下版本,所以我们选择使用早期的lavaRestClient客户端来学习。

官方文档地址: Elasticsearch Clients | Elastic

elasticsearch提供的API中,与elasticsearch一切交互都封装在一个名为RestHighLevelClient的类中,必须先完成这个对象的初始化,建立与elasticsearch的连接。

分为三步:

1)在item-service模块中引入esRestHighLevelClient依赖:

<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>

2)因为SpringBoot默认的ES版本是7.17.10,所以我们需要覆盖默认的ES版本:

<properties><elasticsearch.version>7.12.1</elasticsearch.version></properties>

3)初始化RestHighLevelClient:

初始化的语法如下:

RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.150.101:9200")
));

为了单元测试方便,我们创建一个测试类IndexTest,然后将初始化的代码编写在@BeforeEach方法中:

public class ElasticTest {private RestHighLevelClient client;@Testvoid test() {System.out.println("client =" + client);}@BeforeEachvoid setup() {client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://...:9200")));}@AfterEachvoid tearDown() throws IOException {if (client != null) {client.close();}}
}

启动测试

商品表Mapping映射

我们要实现商品搜索,那么索引库的字段肯定要满足页面搜索的需求:

# 商品索引库
PUT /hmall
{"mappings": {"properties": {"id": {"type": "keyword"},"name": {"type": "text","analyzer": ":ik_smart" # 分词器类型},"price": {"type": "integer"},"image": {"type": "keyword","index": false # 不需要参与搜索},"category": {"type": "keyword"},"brabd": {"type": "keyword"},"sold": {"type": "integer"},"commentCount": {"type": "integer","index": false}"isAD": {"type": "boolean"},"updateTime": {"type": "date"}}}

索引库操作

创建索引库的JavaAPI与Restful接口API对比:

删除索引库

查询索引库

代码示例

public class ElasticIndexTest {private RestHighLevelClient client;@Testvoid test() {System.out.println("client =" + client);}@Testvoid testCreateIndex() throws IOException {// 1. 准备Request对象CreateIndexRequest request = new CreateIndexRequest("items");// 2. 准备请求参数//  request.source(请求体数据, 请求体类型);request.source(MAPPING_TEMPLATE, XContentType.JSON);// 3. 发送请求// client.indices() 得到索引库操作对象// client.indices().create(请求参数, 请求可选项)// RequestOptions.DEFAULT 默认的请求选项client.indices().create(request, RequestOptions.DEFAULT);}@Testvoid testGetIndex() throws IOException {// 1. 准备Request对象GetIndexRequest request = new GetIndexRequest("items");// 2. 发送请求// 查询索引库, 返回索引库信息//  GetIndexResponse res = client.indices().get(request, RequestOptions.DEFAULT);// 查询索引库是否存在, 返回布尔值boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);System.out.println("exists = " + exists);}@Testvoid testDelIndex() throws IOException {// 1. 准备Request对象DeleteIndexRequest request = new DeleteIndexRequest("items");// 2. 发送请求client.indices().delete(request, RequestOptions.DEFAULT);}@BeforeEachvoid setup() {client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.1.97:9200")));}@AfterEachvoid tearDown() throws IOException {if (client != null) {client.close();}}private static final String MAPPING_TEMPLATE = "{\n" +"  \"mappings\": {\n" +"    \"properties\": {\n" +"      \"id\": {\n" +"        \"type\": \"keyword\"\n" +"      },\n" +"      \"name\": {\n" +"        \"type\": \"text\",\n" +"        \"analyzer\": \"ik_smart\"\n" +"      },\n" +"      \"price\": {\n" +"        \"type\": \"integer\"\n" +"      },\n" +"      \"image\": {\n" +"        \"type\": \"keyword\",\n" +"        \"index\": false\n" +"      },\n" +"      \"category\": {\n" +"        \"type\": \"keyword\"\n" +"      },\n" +"      \"brabd\": {\n" +"        \"type\": \"keyword\"\n" +"      },\n" +"      \"sold\": {\n" +"        \"type\": \"integer\"\n" +"      },\n" +"      \"commentCount\": {\n" +"        \"type\": \"integer\",\n" +"        \"index\": false\n" +"      },\n" +"      \"isAD\": {\n" +"        \"type\": \"boolean\"\n" +"      },\n" +"      \"updateTime\": {\n" +"        \"type\": \"date\"\n" +"      }\n" +"    }\n" +"  }\n" +"}";
}

文档操作

1. 新增文档

  1. 索引库准备好以后,就可以操作文档了。为了与索引库操作分离,我们创建一个测试类,做两件事情:
  • 初始化RestHighLevelClient
  • 我们的商品数据在数据库,需要利用IHotelService去查询,所以注入这个接口

@SpringBootTest(properties = "spring.profiles.active=local")
public class ElasticDocumentTest {private RestHighLevelClient client;// 这个接口查询数据要访问数据库// 所以要通过properties配置环境变量,激活配置文件 此处是local// 配置文件激活后才能拿到访问数据库的相关数据@Autowiredprivate IItemService itemService;@Testvoid test() {System.out.println("client =" + client);}@BeforeEachvoid setup() {client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.1.97:9200")));}@AfterEachvoid tearDown() throws IOException {if (client != null) {client.close();}}
}

  1. 商品的索引库结构和数据库结构存在查询, 要定义一个与索引库结构对应的实体

@Data
@ApiModel(description = "索引库实体")
public class ItemDoc{@ApiModelProperty("商品id")private String id;@ApiModelProperty("商品名称")private String name;@ApiModelProperty("价格(分)")private Integer price;@ApiModelProperty("商品图片")private String image;@ApiModelProperty("类目名称")private String category;@ApiModelProperty("品牌名称")private String brand;@ApiModelProperty("销量")private Integer sold;@ApiModelProperty("评论数")private Integer commentCount;@ApiModelProperty("是否是推广广告,true/false")private Boolean isAD;@ApiModelProperty("更新时间")private LocalDateTime updateTime;
}

  1. 新增文档的JavaAPI如下:

@SpringBootTest(properties = "spring.profiles.active=local")
public class ElasticDocumentTest {private RestHighLevelClient client;// 这个接口查询数据要访问数据库// 所以要通过properties配置环境变量,激活配置文件 此处是local// 配置文件激活后才能拿到访问数据库的相关数据@Autowiredprivate IItemService itemService;@Testvoid test() {System.out.println("client =" + client);}@Testvoid testAddDoc() throws IOException {//0 准备文档数据//根据id查询数据库数据Item item = itemService.getById(317578);//数据库的商品数据转为搜索库的文档数据ItemDoc itemDoc = BeanUtil.copyProperties(item, ItemDoc.class);//1 准备RequestIndexRequest request = new IndexRequest("items").id(itemDoc.getId());//2 准备请求参数request.source(JSONUtil.toJsonStr(itemDoc), XContentType.JSON);//3 发送请求client.index(request, RequestOptions.DEFAULT);}@BeforeEachvoid setup() {client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.1.97:9200")));}@AfterEachvoid tearDown() throws IOException {if (client != null) {client.close();}}
}

  1. 使用jdk17, 需要增加一个测试启动项的vm配置, 不然会因为高版本造成 seata 报错

  1. 验证文档是否添加成功

2. 查询文档

查询文档包含查询和解析响应结果两部分。对应的IavaAPI如下


public class ElasticDocumentTest {private RestHighLevelClient client;@Testvoid test() {System.out.println("client =" + client);}@Testvoid testGetDoc() throws IOException {//1 准备RequestGetRequest request = new GetRequest("items", "317578");//2 发送请求GetResponse response = client.get(request, RequestOptions.DEFAULT);//3 解析结果String json = response.getSourceAsString();ItemDoc doc = JSONUtil.toBean(json, ItemDoc.class);System.out.println("doc =" + doc);}@BeforeEachvoid setup() {client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.1.97:9200")));}@AfterEachvoid tearDown() throws IOException {if (client != null) {client.close();}}
}

3. 删除文档

删除文档的JavaAPI如下:

public class ElasticDocumentTest {private RestHighLevelClient client;@Testvoid test() {System.out.println("client =" + client);}@Testvoid testDelDoc() throws IOException {//1 准备RequestDeleteRequest request = new DeleteRequest("items", "317578");//2 发送请求client.delete(request, RequestOptions.DEFAULT);}@BeforeEachvoid setup() {client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.1.97:9200")));}@AfterEachvoid tearDown() throws IOException {if (client != null) {client.close();}}
}

4. 修改文档

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

方式一: 全量更新。再次写入id一样的文档,就会删除旧文档,添加新文档。与新增的JavaAPI一致。

方式二: 局部更新。只更新指定部分字段,

public class ElasticDocumentTest {private RestHighLevelClient client;@Testvoid test() {System.out.println("client =" + client);}@Testvoid testUpdateDoc() throws IOException {//1 准备RequestUpdateRequest request = new UpdateRequest("items", "317578");//2 准备请求参数request.doc("price", 100);//3 发送请求client.update(request, RequestOptions.DEFAULT);}@BeforeEachvoid setup() {client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.1.97:9200")));}@AfterEachvoid tearDown() throws IOException {if (client != null) {client.close();}}
}

5. 批量操作

批处理代码流程与之前类似,只不过构建请求会用到一个名为BulkRequest来封装普通的CRUD请求:

批处理的API示例:

public class ElasticDocumentTest {private RestHighLevelClient client;@Testvoid test() {System.out.println("client =" + client);}@Testvoid testBulkDoc() throws IOException {//1 准备RequestBulkRequest request = new BulkRequest();//2 准备请求参数request.add(new IndexRequest("items").id("1").source("json", XContentType.JSON));request.add(new DeleteRequest("items").id("1"));//3 发送请求client.bulk(request, RequestOptions.DEFAULT);}@BeforeEachvoid setup() {client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.1.97:9200")));}@AfterEachvoid tearDown() throws IOException {if (client != null) {client.close();}}
}

把数据库的数据批量添加到索引库

@SpringBootTest(properties = "spring.profiles.active=local")
public class ElasticDocumentTest {private RestHighLevelClient client;// 这个接口查询数据要访问数据库// 所以要通过properties配置环境变量,激活配置文件 此处是local// 配置文件激活后才能拿到访问数据库的相关数据@Autowiredprivate IItemService itemService;@Testvoid test() {System.out.println("client =" + client);}@Testvoid testBulkDoc() throws IOException {int pageNo = 1, pageSize = 500;while (true) {//1 准备文档数据Page<Item> page = itemService.lambdaQuery().eq(Item::getStatus, 1).page(new Page(pageNo, pageSize));List<Item> records = page.getRecords();if (records.isEmpty() || records == null) {return;}//2 准备RequestBulkRequest request = new BulkRequest();//3 准备请求参数for (Item item : records) {request.add(new IndexRequest("items").id(item.getId().toString()).source(JSONUtil.toJsonStr(BeanUtil.copyProperties(item, ItemDoc.class)), XContentType.JSON));}//4 发送请求client.bulk(request, RequestOptions.DEFAULT);//5 翻页pageNo++;}}@BeforeEachvoid setup() {client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.1.97:9200")));}@AfterEachvoid tearDown() throws IOException {if (client != null) {client.close();}}
}


http://www.ppmy.cn/ops/145670.html

相关文章

SpringBoot集成Flowable

一、工作流介绍 1、概念 通过计算机对业务流程的自动化管理。工作流是建立在业务流程的基础上&#xff0c;一个软件的系统核心根本上还是系统的业务流程&#xff0c;工作流只是协助进行业务流程管理。 解决的是&#xff1a;在多个参与者之间按照某种预定义的规则自动进行传递…

如何结合PCA、t-SNE/UMAP与聚类算法进行高维数据分析?

如何结合PCA、t-SNE/UMAP与聚类算法进行高维数据分析&#xff1f; 在处理高维数据时&#xff0c;如何有效地降维并从中提取有价值的信息&#xff0c;一直是数据分析领域中的一个重要问题。我们常常会面临这样一种情况&#xff1a;数据的特征维度过高&#xff0c;传统的聚类算法…

StarRocks 生产部署一套集群,存储空间如何规划?

背景&#xff1a;StarRocks 3.2&#xff0c;存储一体 使用场景&#xff1a;多分析、小查询多单但不高、数据量几百T FE 存储 由于 FE 节点仅在其存储中维护 StarRocks 的元数据&#xff0c;因此在大多数场景下&#xff0c;每个 FE 节点只需要 100 GB 的 HDD 存储&#xff0c…

【AIGC篇】AIGC 引擎:点燃创作自动化的未来之火

&#xff1a;羑悻的小杀马特.-CSDN博客 未来都是惊喜。你生来本应为高山。并非草芥。 引言&#xff1a; 在当今数字化的时代&#xff0c;人工智能生成内容&#xff08;AIGC&#xff09;正以一种前所未有的力量改变着我们的创作领域。它就像一个神秘而强大的魔法师&#xff0c;…

[论文笔记] 从生成到评估:LLM-as-a-judge 的机遇与挑战

https://arxiv.org/pdf/2411.16594 1. LLM-as-a-judge 的引入 传统的评估方法(如 BLEU 和 ROUGE)在处理生成内容的有用性、无害性等细腻属性时表现不足。随着大语言模型(LLM)的发展,提出了 “LLM-as-a-judge”(LLM 作为评估者)的新范式,用于对任务进行评分、排序或选择…

QT 控件定义为智能指针引发的bug

问题描述&#xff1a; std::unique_ptr<QStackedLayout> m_stacked_layout; 如上为定义&#xff1b; 调用&#xff1a; Line13ABClient::Line13ABClient(QWidget *parent) : BaseWidget(parent) { // 成员变量初始化 m_get_ready false; m_tittle_wnd…

青少年编程与数学 02-004 Go语言Web编程 19课题、API文档

青少年编程与数学 02-004 Go语言Web编程 19课题、API文档 一、API文档二、生成工具三、使用Swagger步骤 1&#xff1a;安装必要的工具步骤 2&#xff1a;安装Swagger相关的Go库步骤 3&#xff1a;编写API代码并添加注释步骤 4&#xff1a;生成Swagger文档步骤 5&#xff1a;运行…

获取菜单路由名称item.meta.title报错Cannot read properties of undefined (reading ‘title‘)

原代码 因为下面路由忘记配置meta&#xff0c;所以获取不到title&#xff0c;添加?进行判断即可 改为 或添加meta