开发者

ElasticSearch自定义注解增删改方式

开发者 https://www.devze.com 2025-04-18 10:23 出处:网络 作者: guoyangsheng_
目录导入依赖导入 ElasticSearchUtil 工具导入config注解类DocumentIndex注解类IdIndex注解类PropertyIndexcontrollerservice实现层 直接调用工具类方法即可总结导入依赖
目录
  • 导入依赖
  • 导入 ElasticSearchUtil 工具
  • 导入config
    • 注解类DocumentIndex
    • 注解类IdIndex
    • 注解类PropertyIndex
    • controller
    • service
  • 实现层 直接调用工具类方法即可
    • 总结

      导入依赖

      <!--提供与 Elasticsearch 交互的高层次客户端,便于在 Java 应用中使用 Elasticsearch 的功能。-->
      <dependency>
          <groupId>org.elasticsearch.client</groupId>
          <artifactId>elasticsearch-rest-high-level-client</artifactId>
      </dependency>
      <!-- Spring Boot 的起始器,简化了与 Elasticsearch 的集成 -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
      </dependency>
      <!-- 高性能的 jsON 处理库,用于 JSON 的解析和生成 -->
      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>fastjson</artifactId>
          <version>1.2.83</version> <!-- 请使用最新的版本 -->
      </dependency>
      <!-- 通过注解简化 Java 代码,自动生成 getter、setter、构造函数等代码,减少样板代码的编写 -->
      <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
      </dependency>

      导入 ElasticSearchUtil 工具

      @Component
      @Slf4j
      public class ElasticSearchUtil {
          @Autowired
          private RestHighLevelClient restHighLevelClient;
      
          /**
           * 取对象id
           *
           * @param data
           * @return
           */
          private String getObjectId(Object data) {
              String idValue = null;
              try {
                  String idName = "id";
                  //获取Object类下所有字段
       http://www.devze.com           Field[] declaredFields = data.getClass().getDeclaredFields();
                  //循环遍历
                  for (Field field : declaredFields) {
                      //获取字段上的'IdIndex'的注解实例
                      IdIndex annotation = field.getAnnotation(IdIndex.class);
                      //如果不为空
                      if (annotation != null) {
                          //将annotation中的idNamejavascript赋给变量idName
                          idName = annotation.idName();
                          //终止循环
                          break;
                      }
                  }
                  //查找一个名为 idName 的字段,并返回一个 Field 对象,表示这个字段
                  Field declaredField = data.getClass().getDeclaredField(idName);
                  //设置对象的访问权限
                  declaredField.setAccessible(true);
                  idValue = declaredField.get(data).toString();
                  log.info(" >>>>>> idValue:{}", idValue);
              } catch (Exception e) {
                  log.error(e.getMessage());
              }
              return idValue;
          }
      
          /**
           * 创建索引
           *
           * @return
           * @params index
           */
          public String createIndex(Object data) throws Exception {
              //根据实体注解取索引名字
              DocumentIndex annotation = data.getClass().getAnnotation(DocumentIndex.class);
              String indexName = annotation.indexName();
      
              //索引已经存在,不需要创建索引
              if (isIndexExist(indexName)) return indexName;
      
              //1.创建索引请求
              CreateIndexRequest request = new CreateIndexRequest(indexName);
      
              //创建基础配置
              Settings.Builder builder = Settings.builder().put("index.max_result_window", annotation.maxSize());//10亿数据
              builder.put("index.number_of_shards", annotation.shards()) // 分片数量
                      .put("index.number_of_replicas", annotation.replicas()); // 副本数量
              request.settings(builder);//索引文档基础配置
      
              //mapping结构
              JSONObject mapping = new JSONObject();
              JSONObject props = new JSONObject();
              mapping.put("properties", props);
      
              Class<?> aClass = data.getClass();
              //aClass.getConstructors();
              //aClass.getMethods();
              //取对象所有私有属性
              Field[] declaredFields = aClass.getDeclaredFields();
              for (Field field : declaredFields) {
                  Class type = field.getType();
                  String name = field.getName();
                  JSONObject prop = new JSONObject();
                  PropertyIndex propIndex = field.getAnnotation(PropertyIndex.class);
                  if (propIndex != null) {//自定义属性各种配置
                      if (propIndex.name() != null && !"".equals(propIndex.name())) {
                          name = propIndex.name();
                      }
                      props.put(name, prop);//通过注解可以指定索引字段名称
                      prop.put("type", propIndex.type());
                      prop.put("index", true);//默认true
                      if ("text".equals(propIndex.type())) {
                          prop.put("analyzer", propIndex.analyzer());//"analyzer": "ik_max_word",
                          prop.put("search_analyzer", propIndex.searchAnalyzer());//"search_analyzer": "ik_smart"
                      }
                      if (!propIndex.index()) { //设置非索引
                          prop.put("index", false);
                      }
                  } else { //默认处理
                      props.put(name, prop);
                      if (type.newInstance() instanceof String) {
                          prop.put("type", "keyword");
                      } else if (type.newInstance() instanceof Date) {
                          prop.put("type", "date");
                          prop.put("format", "yyyy-MM-dd HH:mm:ss");//"format": "yyyy-MM-dd HH:mm:ss"
                      } else if (type.newInstance() instanceof Integer) {
                          prop.put("type", "integer");
                      } else if (type.newInstance() instanceof Long) {
                          prop.put("type", "long");
                      } else {
                          prop.put("type", "text");
                          prop.put("analyzer", "ik_smart");//"analyzer": "ik_max_word",
                          prop.put("search_analyzer", "ik_smart");//"search_analyzer": "ik_smart"
                      }
                  }
      
              }
      
              String jsonString = mapping.toJSONString();
              log.info("jsonString: " + jsonString);
              request.mapping("_doc", jsonString, XContentType.JSON);
      
              //2.执行客户端请求
              CreateIndexResponse createIndexResponse = restHighLevelClient.indices()
                      .create(request, RequestOptions.DEFAULT);
      
              return indexName;
          }
      
          /**
           * 判断索引是否存在
           *
           * @param index
           * @return
           */
          public boolean isIndexExist(String index) throws IOException {
              GetIndexRequest request = new GetIndexRequest(index);
              boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
              return exists;
          }
      
          /**
           * 删除索引
           *
           * @param index
           * @return
           */
          public boolean deleteIndex(String index) throws IOException {
              if (!isIndexExist(index)) {
                  log.error("Index is not exits!");
                  return false;
              }
              DeleteIndexRequest request = new DeleteIndexRequest(index);
              org.elasticsearch.action.support.master.AcknowledgedResponse delete = restHighLevelClient.indices()
                      .delete(request, RequestOptions.DEFAULT);
              return delete.isAcknowledged();
          }
      
          /**
           * 写入数据
           */
          public boolean insertData(Object data, String indexName) {
              try {
                  IndexRequest request = new IndexRequest(indexName).id(getObjectId(data)).source(JSON.toJSONString(data), XContentType.JSON);
                  restHighLevelClient.index(request, RequestOptions.DEFAULT);
              } catch (Exception e) {
                  log.info(" >>>>>>> insertData error: {}", e.getMessage());
                  e.printStackTrace();
              }
              return true;
          }
      
          /**
           * 批量写入数据
           */
          public boolean BATchInsert(List<Object> datas) {
              //参数校验
              if (CollectionUtils.isEmpty(datas)) return false;
      
              DocumentIndex annotation = datas.get(0).getClass().getAnnotation(DocumentIndex.class);
              String indexName = annotation.indexName();
      
              try {
                  BulkRequest bulkRequest = new BulkRequest();
      
                  datas.forEach(data -> {
                      bulkRequest.add(new IndexRequest(indexName).id(getObjectId(data))
                              .source(JSON.toJSONString(data), XContentType.JSON));
                  });
      
                  restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
              } catch (Exception e) {
                  log.info(" >>>>>>> insertData error: {}", e.getMessage());
                  e.printStackTrace();
              }
              return true;http://www.devze.com
          }
      
          /**
           * 更新数据,可以直接修改索引结构
           */
          public boolean batchUpdate(List<Object> datas) {
      
              if (CollectionUtils.isEmpty(datas)) return false;
      
              DocumentIndex annotation = datas.get(0).getClass().getAnnotation(DocumentIndex.class);
              String indexName = annotation.indexName();
              try {
                  BulkRequest bulkRequest = new BulkRequest();
      
                  datas.forEach(data -> {
                      bulkRequest.add(new UpdateRequest(indexName, "doc", getObjectId(data)).doc(JSON.toJSONString(data)));
                  });
      
                  restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
              } catch (Exception e) {
                  log.info(" >>>>>>> insertData error: {}", e.getMessage());
                  e.printStackTrace();
              }
      
              return trphpue;
          }
      
          /**
           * 修改
           *
           * @param data
           * @return
           */
          public boolean updateData(Object data) {
              try {
                  //获取索引名
                  String indexName = data.getClass().getAnnotation(DocumentIndex.class).indexName();
                  //创建修改请求
                  UpdateRequest updateRequest = new UpdateRequest(indexName, "_doc", getObjectId(data)).doc(JSON.toJSONString(data), XContentType.JSON);
                  restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
              } catch (IOException e) {
                  log.info(" >>>>>>> updateData error: {}", e.getMessage());
                  e.printStackTrace();
              }
              return true;
          }
      
          /**
           * 删除数据
           */
          public boolean delete(String indexName, String id) {
              try {
                  DeleteRequest deleteRequest = new DeleteRequest(indexName, "_doc", id);
                  restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
              } catch (Exception e) {
                  log.error(" delete Exception:{}", e.getMessage());
                  e.printStackTrace();
              }
              return true;
          }
      
      }

      导入config

      @Configuration
      public class InitRestHighLevelClient  {
      
          @Value("${es.hostname:IP}")
      javascript    private String hostname;
      
          @Value("${es.port:端口}")
          private int port;
      
          /**
           * 初始化 RestHighLevelClient 对象
           *
           * @return
           */
          @Bean
          public RestHighLevelClient restHighLevelClient() {
              RestHighLevelClient client = new RestHighLevelClient(
                      RestClient.builder(new HttpHost(hostname, port, "http"))
              );
              return client;
          }
      }

      注解类DocumentIndex

      /**
       * @Author:GuoYangsheng
       * @Description:
       * @name:DocumentIndex
       * @Date:2024/9/12 16:43
       */
      @Target(ElementType.TYPE)//指定注解可以应用于类、接口或枚举
      @Retention(RetentionPolicy.RUNTIME)//可以通过反射机制访问和读取
      public @interface DocumentIndex {
      
          //指定索引的名称。默认为空字符串,表示未指定
          String indexName() default "";
      
          //默认为索引的文档数量上限为10000
          int maxSize() default 10000;
      
          //指定索引的分片数量 默认为3 分片可以提高索引的性能和可扩展性
          int shards() default 3;
      
          //指定索引的副本数量 默认为1 副本可以提高数据的可靠性和查询性能
          int replicas() default 1;
      }

      注解类IdIndex

      /**
       * @Author:GuoYangsheng
       * @Description:
       * @name:IdIndex
       * @Date:2024/9/12 16:50
       */
      @Target(ElementType.FIELD)//指定 ‘IdIndex' 可以应用于类中字段上
      @Retention(RetentionPolicy.RUNTIME)//可以通过反射机制访问和读取
      public @interface IdIndex {
          //指定属性标识符名称为 'id'
          String idName() default "id";
      }

      注解类PropertyIndex

      /**
       * @Author:GuoYangsheng
       * @Description:
       * @name:PropertyIndex
       * @Date:2024/9/12 16:58
       */
      
      import java.lang.annotation.ElementType;
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      import java.lang.annotation.Target;
      
      /**
       * ES索引字段注解
       */
      @Target(ElementType.FIELD)//指定 ‘IdIndex' 可以应用于类中字段上
      @Retention(RetentionPolicy.RUNTIME)//可以通过反射机制访问和读取
      public @interface PropertyIndex {
          //用于指定字段在Elasticsearch索引中的名称
          String name() default "";
          //指定字段的数据类型
          String type() default "keyword";
          //指定用于字段的分词器
          String analyzer() default "ik_smart";
          //是否建立索引
          boolean index() default true;
          //指定用于搜索时的分词器
          String searchAnalyzer() default "ik_smart";
          //指定是否忽略该字段的索引
          boolean ignore() default true;
      }

      controller

      /**
       * @Author:GuoYangsheng
       * @Description:
       * @name:SysDeptController
       * @Date:2024/9/12 20:26
       */
      @RestController
      @RequestMapping("/sysDept")
      public class SysDeptController {
          @Autowired
          private SysDeptService sysDeptService;
      
          /**
           * 创建索引
           *
           * @param sysDept
           * @return
           */
          @GetMapping("/createIndex")
          public void createIndex(SysDept sysDept) {
              sysDeptService.createIndex(sysDept);
          }
      
          /**
           * 保存
           *
           * @param sysDept
           */
          @PostMapping("/save")
          public Boolean save(@RequestBody SysDept sysDept) {
              return sysDeptService.save(sysDept);
          }
      
          /**
           * 删除数据
           *
           * @param indexName
           * @param id
           * @return
           */
          @DeleteMapping("/deleteById")
          public Boolean deleteById(String indexName, String id) {
              return sysDeptService.deleteById(indexName, id);
          }
      
          /**
           * 修改数据
           *
           * @param sysDept
           * @return
           */
          @PutMapping("/updateSysDept")
          public Boolean updateSysDept(@RequestBody SysDept sysDept) {
              return sysDeptService.updateSysDept(sysDept);
          }
      }

      service

      /**
       * @Author:GuoYangsheng
       * @Description:
       * @name:SysDeptService
       * @Date:2024/9/12 20:26
       */
      public interface SysDeptService {
          /**
           * 创建索引
           *
           * @param sysDept
           */
          void createIndex(SysDept sysDept);
      
          /**
           * 保存
           *
           * @param sysDept
           */
          Boolean save(SysDept sysDept);
      
      
          /**
           * 删除数据
           *
           * @param indexName
           * @param id
           * @return
           */
          Boolean deleteById(String indexName, String id);
      
          /**
           * 修改数据
           *
           * @param sysDept
           * @return
           */
          Boolean updateSysDept(SysDept sysDept);
      }

      实现层 直接调用工具类方法即可

      /**
       * @Author:GuoYangsheng
       * @Description:
       * @name:SysDeptServiceImpl
       * @Date:2024/9/12 20:26
       */
      @Service
      public class SysDeptServiceImpl implements SysDeptService {
          @Resource
          private ElasticSearchUtil elasticSearchUtil;
      
          /**
           * 创建索引
           *
           * @param sysDept
           */
          @Override
          public void createIndex(SysDept sysDept) {
              try {
                  elasticSearchUtil.createIndex(sysDept);
              } catch (Exception e) {
                  throw new RuntimeException(e);
              }
          }
      
          /**
           * 保存
           *
           * @param sysDept
           */
          @Override
          public Boolean save(SysDept sysDept) {
              return elasticSearchUtil.insertData(sysDept);
          }
      
      
          /**
           * 删除数据
           *
           * @param indexName
           * @param id
           * @return
           */
          @Override
          public Boolean deleteById(String indexName, String id) {
      
              return elasticSearchUtil.delete(indexName, id);
          }
      
          /**
           * 修改数据
           *
           * @param sysDept
           * @return
           */
          @Override
          public Boolean updateSysDept(SysDept sysDept) {
      
              return elasticSearchUtil.updateData(sysDept);
          }
      }

      在Elastic开发工具中查看效果,或者下载Apipost工具测试即可

      总结

      以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

      0

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      关注公众号