Elasticsearch封装公共索引增删改查
什么是索引?
- 定义:索引是 Elasticsearch 中用于存储数据的逻辑命名空间。它由多个文档组成,每个文档是一个 JSON 格式的结构化数据
- 对应关系:在关系数据库中,索引类似于表;而在 Elasticsearch 中,索引则相当于数据库的集合或目录。
依赖
选择方案一
使用这个依赖的话必须搭配配置类去使用
<!-- elasticsearch --><dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.7.0</version></dependency><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.7.0</version></dependency>
选择方案二
使用这个依赖的话配置类可写可不写,因为springboot工程已经帮我们自动的去完成配置了,不需要我们自己写了
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency>
配置
es:host: 111.229.0.43port: 9200scheme: http
配置类
package com.macro.mall.demo.config;import lombok.Data;
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.stereotype.Component;@Data
@Component
public class InitEsRes {@Value("${es.host}")private String host;@Value("${es.port}")private int port;@Value("${es.scheme}")private String scheme;@Beanpublic RestHighLevelClient restHighLevelClient(){return new RestHighLevelClient(RestClient.builder(new HttpHost(host,port,scheme)));}
}
dto
package com.macro.mall.demo.dto;import io.swagger.annotations.ApiModelProperty;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;/*** @Author:xsp* @Description: es索引传输对象* @name:EsIndexDto* @Date:2024/10/16 15:30*/
@Data
public class EsIndexDto {/*** 索引名称*/@NotEmpty(message = "索引名称不能为空")@ApiModelProperty(value = "索引名称", required = true, example = "。。。。")private String indexName;/*** 索引映射*/@ApiModelProperty(value = "索引映射", required = true, example = "。。。。")private String indexMappings;/*** 索引配置*/@ApiModelProperty(value = "索引配置", required = true, example = "。。。。")private String indexSettings;}
controller
package com.macro.mall.demo.controller;import com.macro.mall.common.api.CommonResult;
import com.macro.mall.demo.dto.EsIndexDto;
import com.macro.mall.demo.service.EsIndexService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jakarta.validation.constraints.NotEmpty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;import java.util.Map;/*** @Author:xsp* @Description: es索引管理* @name:EsController* @Date:2024/10/15 20:38*/
@RestController
@RequestMapping("/index")
@Validated
@Api(tags = "es索引管理")
public class EsIndexController {@Autowiredprivate EsIndexService esIndexService;/*** 创建索引的接口* @param esIndexDto 索引信息* @return*/@ApiOperation(value = "创建索引")@PostMapping("/create")public CommonResult createIndex(@Validated @RequestBody EsIndexDto esIndexDto) {esIndexService.createIndex(esIndexDto);return CommonResult.successMessage("索引创建成功"); // 调用服务方法创建索引}/*** 删除索引的接口* @param indexName 索引名称* @return*/@ApiOperation(value = "删除索引")@DeleteMapping("/delete")public CommonResult deleteIndex(@RequestParam @NotEmpty(message = "索引名称不能为空") String indexName) {esIndexService.deleteIndex(indexName); // 调用服务方法删除索引return CommonResult.successMessage("索引删除成功");}/*** 获取索引的接口* @param indexName 索引名称* @return*/@ApiOperation(value = "获取索引映射")@GetMapping("/get")public CommonResult<Map<String, Object>> getIndex(@RequestParam @NotEmpty(message = "索引名称不能为空") String indexName) {Map<String, Object> indexMappings = esIndexService.getIndex(indexName);return CommonResult.success(indexMappings); // 调用服务方法获取索引}/*** 根据索引名称修改索引配置* @param esIndexDto 索引信息* @return*/@ApiOperation(value = "修改索引配置")@PutMapping("/update")public CommonResult updateIndex(@Validated @RequestBody EsIndexDto esIndexDto) {esIndexService.updateIndex(esIndexDto);return CommonResult.successMessage("索引更新成功"); // 调用服务方法更新索引}/*** 判断索引是否存在* @param indexName 索引名称* @return*/@ApiOperation(value = "判断索引是否存在")@GetMapping("/exists")public CommonResult exists(@RequestParam @NotEmpty(message = "索引名称不能为空") String indexName) {boolean exists =esIndexService.exists(indexName);return CommonResult.success(exists);}
}
serveice
package com.macro.mall.demo.service;import com.macro.mall.demo.dto.EsDocDto;
import com.macro.mall.demo.dto.EsIndexDto;import java.util.List;
import java.util.Map;/*** @Author:xsp* @Description:* @name:EsService* @Date:2024/10/15 20:39*/
public interface EsDocService {/*** 批量添加* @param esDocDto 文档信息*/void batchAdd(EsDocDto esDocDto);/*** 批量删除* @param indexName 索引名称* @param ids 多个id*/void batchDelete(String indexName, List<String> ids);
}
impl
package com.macro.mall.demo.service.impl;import com.macro.mall.demo.dto.EsDocDto;
import com.macro.mall.demo.dto.EsIndexDto;
import com.macro.mall.demo.service.EsIndexService;
import lombok.extern.log4j.Log4j2;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.Map;/*** @Author:xsp* @Description:* @name:EsServiceImpl* @Date:2024/10/15 20:39*/
@Service
@Slf4j
public class EsIndexServiceImpl implements EsIndexService {@Autowiredprivate RestHighLevelClient restHighLevelClient;/*** 创建索引** @param esIndexDto 索引信息*/@Overridepublic void createIndex(EsIndexDto esIndexDto) {// 检查索引是否已存在if (exists(esIndexDto.getIndexName())) {throw new RuntimeException("索引已经存在: " + esIndexDto.getIndexName());}// 创建索引请求CreateIndexRequest request = new CreateIndexRequest(esIndexDto.getIndexName());// 设置索引配置if (StringUtils.isNotBlank(esIndexDto.getIndexMappings())) {request.settings("_doc",esIndexDto.getIndexMappings(), XContentType.JSON);}// 执行创建索引操作try {restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);log.info("索引创建成功: {}", esIndexDto.getIndexName());} catch (Exception e) {log.error("创建索引失败, 错误信息: {}", e.getMessage());throw new RuntimeException("创建索引失败: " + esIndexDto.getIndexName(), e);}}/*** 删除索引** @param indexName 索引名称*/@Overridepublic void deleteIndex(String indexName) {// 检查索引是否存在if (!exists(indexName)) {throw new RuntimeException("索引不存在: " + indexName);}// 创建删除索引请求DeleteIndexRequest request = new DeleteIndexRequest(indexName);// 执行删除索引操作try {restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);log.info("索引删除成功: {}", indexName);} catch (Exception e) {log.error("删除索引失败, 错误信息: {}", e.getMessage());throw new RuntimeException("删除索引失败: " + indexName, e);}}/*** 获取索引映射** @param indexName 索引名称* @return 索引映射信息*/@Overridepublic Map<String, Object> getIndex(String indexName) {// 检查索引是否存在if (!exists(indexName)) {throw new RuntimeException("索引不存在: " + indexName);}// 创建获取索引请求GetIndexRequest request = new GetIndexRequest(indexName);// 执行获取索引映射操作try {GetIndexResponse response = restHighLevelClient.indices().get(request, RequestOptions.DEFAULT);log.info("获取索引映射成功: {}", indexName);return response.getMappings().get(indexName).sourceAsMap(); // 返回索引映射} catch (Exception e) {log.error("获取索引映射失败, 错误信息: {}", e.getMessage());throw new RuntimeException("获取索引映射失败: " + indexName, e);}}/*** 更新索引配置** @param esIndexDto 索引信息*/@Overridepublic void updateIndex(EsIndexDto esIndexDto) {// 检查索引是否存在if (!exists(esIndexDto.getIndexName())) {throw new RuntimeException("索引不存在: " + esIndexDto.getIndexName());}// 创建更新索引设置请求UpdateSettingsRequest request = new UpdateSettingsRequest(esIndexDto.getIndexName());// 更新索引映射if (StringUtils.isNotBlank(esIndexDto.getIndexMappings())) {request.settings(esIndexDto.getIndexMappings(), XContentType.JSON);}// 执行更新索引设置操作try {boolean acknowledged = restHighLevelClient.indices().putSettings(request, RequestOptions.DEFAULT).isAcknowledged();if (acknowledged) {log.info("索引设置更新成功: {}", esIndexDto.getIndexName());} else {log.warn("索引设置更新未被确认: {}", esIndexDto.getIndexName());}} catch (Exception e) {log.error("更新索引设置失败, 错误信息: {}", e.getMessage());throw new RuntimeException("更新索引设置失败: " + esIndexDto.getIndexName(), e);}}/*** 判断索引是否存在** @param indexName 索引名称* @return 索引是否存在*/@Overridepublic boolean exists(String indexName) {// 创建获取索引请求GetIndexRequest request = new GetIndexRequest(indexName);try {// 执行获取索引操作并返回索引是否存在boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);log.info("判断索引是否存在: {}, 结果: {}", indexName, exists);return exists;} catch (Exception e) {log.error("判断索引是否存在失败, 错误信息: {}", e.getMessage());return false; // 返回判断失败}}}
统一结果集
package com.macro.mall.common.api;import cn.hutool.json.JSONUtil;/*** 通用返回对象* Created by 9a8204a7-f77d-4ab8-ae70-b4721fef2f95 on 2019/4/19.*/
public class CommonResult<T> {private long code;private String message;private T data;protected CommonResult() {}protected CommonResult(long code, String message, T data) {this.code = code;this.message = message;this.data = data;}/*** 成功返回信息* @param message 提示信息*/public static <T> CommonResult<T> successMessage(String message) {return new CommonResult<T>(ResultCode.SUCCESS.getCode(), message, null);}/*** 成功返回结果** @param data 获取的数据*/public static <T> CommonResult<T> success(T data) {return new CommonResult<T>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMessage(), data);}/*** 成功返回结果** @param data 获取的数据* @param message 提示信息*/public static <T> CommonResult<T> success(T data, String message) {return new CommonResult<T>(ResultCode.SUCCESS.getCode(), message, data);}/*** 失败返回结果* @param errorCode 错误码*/public static <T> CommonResult<T> failed(IErrorCode errorCode) {return new CommonResult<T>(errorCode.getCode(), errorCode.getMessage(), null);}/*** 失败返回结果* @param errorCode 错误码* @param message 错误信息*/public static <T> CommonResult<T> failed(IErrorCode errorCode,String message) {return new CommonResult<T>(errorCode.getCode(), message, null);}/*** 失败返回结果* @param message 提示信息*/public static <T> CommonResult<T> failed(String message) {return new CommonResult<T>(ResultCode.FAILED.getCode(), message, null);}/*** 失败返回结果*/public static <T> CommonResult<T> failed() {return failed(ResultCode.FAILED);}/*** 参数验证失败返回结果*/public static <T> CommonResult<T> validateFailed() {return failed(ResultCode.VALIDATE_FAILED);}/*** 参数验证失败返回结果* @param message 提示信息*/public static <T> CommonResult<T> validateFailed(String message) {return new CommonResult<T>(ResultCode.VALIDATE_FAILED.getCode(), message, null);}/*** 未登录返回结果*/public static <T> CommonResult<T> unauthorized(T data) {return new CommonResult<T>(ResultCode.UNAUTHORIZED.getCode(), ResultCode.UNAUTHORIZED.getMessage(), data);}/*** 未授权返回结果*/public static <T> CommonResult<T> forbidden(T data) {return new CommonResult<T>(ResultCode.FORBIDDEN.getCode(), ResultCode.FORBIDDEN.getMessage(), data);}public long getCode() {return code;}public void setCode(long code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public T getData() {return data;}public void setData(T data) {this.data = data;}@Overridepublic String toString() {return JSONUtil.toJsonStr(this);}
}
这里我用的是这个统一结果集,结合自己实际情况去使用相对应的统一结果集
Spring原生效验异常
@ResponseBody@ExceptionHandler(value = ApiException.class)public CommonResult handle(ApiException e) {if (e.getErrorCode() != null) {return CommonResult.failed(e.getErrorCode());}return CommonResult.failed(e.getMessage());}@ResponseBody@ExceptionHandler(value = MethodArgumentNotValidException.class)public CommonResult handleValidException(MethodArgumentNotValidException e) {BindingResult bindingResult = e.getBindingResult();String message = null;if (bindingResult.hasErrors()) {FieldError fieldError = bindingResult.getFieldError();if (fieldError != null) {message = fieldError.getField()+fieldError.getDefaultMessage();}}return CommonResult.validateFailed(message);}@ResponseBody@ExceptionHandler(value = BindException.class)public CommonResult handleValidException(BindException e) {BindingResult bindingResult = e.getBindingResult();String message = null;if (bindingResult.hasErrors()) {FieldError fieldError = bindingResult.getFieldError();if (fieldError != null) {message = fieldError.getField()+fieldError.getDefaultMessage();}}return CommonResult.validateFailed(message);}/*** 最大异常* @param e* @return*/@ResponseBody@ExceptionHandler(value = Exception.class)public CommonResult handle(Exception e) {e.printStackTrace();return CommonResult.validateFailed(e.getMessage());}
这里我是用的这几个写的异常捕获器,结合自己实际情况去使用相对应的异常捕获
目前先更新到这里,后期补发