ElasticSearch自定義注解增刪改方式
更新時(shí)間:2025年04月17日 09:46:43 作者:guoyangsheng_
這篇文章主要介紹了ElasticSearch自定義注解增刪改方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
導(dǎo)入依賴
<!--提供與 Elasticsearch 交互的高層次客戶端,便于在 Java 應(yīng)用中使用 Elasticsearch 的功能。-->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
<!-- Spring Boot 的起始器,簡(jiǎn)化了與 Elasticsearch 的集成 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<!-- 高性能的 JSON 處理庫(kù),用于 JSON 的解析和生成 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version> <!-- 請(qǐng)使用最新的版本 -->
</dependency>
<!-- 通過(guò)注解簡(jiǎn)化 Java 代碼,自動(dòng)生成 getter、setter、構(gòu)造函數(shù)等代碼,減少樣板代碼的編寫 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>導(dǎo)入 ElasticSearchUtil 工具
@Component
@Slf4j
public class ElasticSearchUtil {
@Autowired
private RestHighLevelClient restHighLevelClient;
/**
* 取對(duì)象id
*
* @param data
* @return
*/
private String getObjectId(Object data) {
String idValue = null;
try {
String idName = "id";
//獲取Object類下所有字段
Field[] declaredFields = data.getClass().getDeclaredFields();
//循環(huán)遍歷
for (Field field : declaredFields) {
//獲取字段上的'IdIndex'的注解實(shí)例
IdIndex annotation = field.getAnnotation(IdIndex.class);
//如果不為空
if (annotation != null) {
//將annotation中的idName賦給變量idName
idName = annotation.idName();
//終止循環(huán)
break;
}
}
//查找一個(gè)名為 idName 的字段,并返回一個(gè) Field 對(duì)象,表示這個(gè)字段
Field declaredField = data.getClass().getDeclaredField(idName);
//設(shè)置對(duì)象的訪問(wèn)權(quán)限
declaredField.setAccessible(true);
idValue = declaredField.get(data).toString();
log.info(" >>>>>> idValue:{}", idValue);
} catch (Exception e) {
log.error(e.getMessage());
}
return idValue;
}
/**
* 創(chuàng)建索引
*
* @return
* @params index
*/
public String createIndex(Object data) throws Exception {
//根據(jù)實(shí)體注解取索引名字
DocumentIndex annotation = data.getClass().getAnnotation(DocumentIndex.class);
String indexName = annotation.indexName();
//索引已經(jīng)存在,不需要?jiǎng)?chuàng)建索引
if (isIndexExist(indexName)) return indexName;
//1.創(chuàng)建索引請(qǐng)求
CreateIndexRequest request = new CreateIndexRequest(indexName);
//創(chuàng)建基礎(chǔ)配置
Settings.Builder builder = Settings.builder().put("index.max_result_window", annotation.maxSize());//10億數(shù)據(jù)
builder.put("index.number_of_shards", annotation.shards()) // 分片數(shù)量
.put("index.number_of_replicas", annotation.replicas()); // 副本數(shù)量
request.settings(builder);//索引文檔基礎(chǔ)配置
//mapping結(jié)構(gòu)
JSONObject mapping = new JSONObject();
JSONObject props = new JSONObject();
mapping.put("properties", props);
Class<?> aClass = data.getClass();
//aClass.getConstructors();
//aClass.getMethods();
//取對(duì)象所有私有屬性
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);//通過(guò)注解可以指定索引字段名稱
prop.put("type", propIndex.type());
prop.put("index", true);//默認(rèn)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()) { //設(shè)置非索引
prop.put("index", false);
}
} else { //默認(rèn)處理
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.執(zhí)行客戶端請(qǐng)求
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();
}
/**
* 寫入數(shù)據(jù)
*/
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;
}
/**
* 批量寫入數(shù)據(jù)
*/
public boolean batchInsert(List<Object> datas) {
//參數(shù)校驗(yàn)
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;
}
/**
* 更新數(shù)據(jù),可以直接修改索引結(jié)構(gòu)
*/
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 true;
}
/**
* 修改
*
* @param data
* @return
*/
public boolean updateData(Object data) {
try {
//獲取索引名
String indexName = data.getClass().getAnnotation(DocumentIndex.class).indexName();
//創(chuàng)建修改請(qǐng)求
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;
}
/**
* 刪除數(shù)據(jù)
*/
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;
}
}導(dǎo)入config
@Configuration
public class InitRestHighLevelClient {
@Value("${es.hostname:IP}")
private String hostname;
@Value("${es.port:端口}")
private int port;
/**
* 初始化 RestHighLevelClient 對(duì)象
*
* @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)//指定注解可以應(yīng)用于類、接口或枚舉
@Retention(RetentionPolicy.RUNTIME)//可以通過(guò)反射機(jī)制訪問(wèn)和讀取
public @interface DocumentIndex {
//指定索引的名稱。默認(rèn)為空字符串,表示未指定
String indexName() default "";
//默認(rèn)為索引的文檔數(shù)量上限為10000
int maxSize() default 10000;
//指定索引的分片數(shù)量 默認(rèn)為3 分片可以提高索引的性能和可擴(kuò)展性
int shards() default 3;
//指定索引的副本數(shù)量 默認(rèn)為1 副本可以提高數(shù)據(jù)的可靠性和查詢性能
int replicas() default 1;
}注解類IdIndex
/**
* @Author:GuoYangsheng
* @Description:
* @name:IdIndex
* @Date:2024/9/12 16:50
*/
@Target(ElementType.FIELD)//指定 ‘IdIndex' 可以應(yīng)用于類中字段上
@Retention(RetentionPolicy.RUNTIME)//可以通過(guò)反射機(jī)制訪問(wèn)和讀取
public @interface IdIndex {
//指定屬性標(biāo)識(shí)符名稱為 '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' 可以應(yīng)用于類中字段上
@Retention(RetentionPolicy.RUNTIME)//可以通過(guò)反射機(jī)制訪問(wèn)和讀取
public @interface PropertyIndex {
//用于指定字段在Elasticsearch索引中的名稱
String name() default "";
//指定字段的數(shù)據(jù)類型
String type() default "keyword";
//指定用于字段的分詞器
String analyzer() default "ik_smart";
//是否建立索引
boolean index() default true;
//指定用于搜索時(shí)的分詞器
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;
/**
* 創(chuàng)建索引
*
* @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);
}
/**
* 刪除數(shù)據(jù)
*
* @param indexName
* @param id
* @return
*/
@DeleteMapping("/deleteById")
public Boolean deleteById(String indexName, String id) {
return sysDeptService.deleteById(indexName, id);
}
/**
* 修改數(shù)據(jù)
*
* @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 {
/**
* 創(chuàng)建索引
*
* @param sysDept
*/
void createIndex(SysDept sysDept);
/**
* 保存
*
* @param sysDept
*/
Boolean save(SysDept sysDept);
/**
* 刪除數(shù)據(jù)
*
* @param indexName
* @param id
* @return
*/
Boolean deleteById(String indexName, String id);
/**
* 修改數(shù)據(jù)
*
* @param sysDept
* @return
*/
Boolean updateSysDept(SysDept sysDept);
}實(shí)現(xiàn)層 直接調(diào)用工具類方法即可
/**
* @Author:GuoYangsheng
* @Description:
* @name:SysDeptServiceImpl
* @Date:2024/9/12 20:26
*/
@Service
public class SysDeptServiceImpl implements SysDeptService {
@Resource
private ElasticSearchUtil elasticSearchUtil;
/**
* 創(chuàng)建索引
*
* @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);
}
/**
* 刪除數(shù)據(jù)
*
* @param indexName
* @param id
* @return
*/
@Override
public Boolean deleteById(String indexName, String id) {
return elasticSearchUtil.delete(indexName, id);
}
/**
* 修改數(shù)據(jù)
*
* @param sysDept
* @return
*/
@Override
public Boolean updateSysDept(SysDept sysDept) {
return elasticSearchUtil.updateData(sysDept);
}
}在Elastic開(kāi)發(fā)工具中查看效果,或者下載Apipost工具測(cè)試即可
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
解決@RequestBody接收json對(duì)象報(bào)錯(cuò)415的問(wèn)題
這篇文章主要介紹了解決@RequestBody接收json對(duì)象報(bào)錯(cuò)415的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
基于idea操作hbase數(shù)據(jù)庫(kù)并映射到hive表
這篇文章主要介紹了用idea操作hbase數(shù)據(jù)庫(kù),并映射到hive,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
Java Map遍歷2種實(shí)現(xiàn)方法代碼實(shí)例
這篇文章主要介紹了Java Map遍歷2種實(shí)現(xiàn)方法代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10
Java實(shí)現(xiàn)簡(jiǎn)易即時(shí)通訊系統(tǒng)的示例詳解
這篇文章主要為大家詳細(xì)介紹了如何使用Java模擬實(shí)現(xiàn)類似QQ的簡(jiǎn)易即時(shí)通訊系統(tǒng),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-06-06
Spring?Boot?實(shí)現(xiàn)?IP?限流(保障系統(tǒng)穩(wěn)定性的關(guān)鍵技術(shù))
在Spring?Boot中實(shí)現(xiàn)IP限流是一種簡(jiǎn)單而有效的方式來(lái)保障系統(tǒng)的穩(wěn)定性和可用性,本文通過(guò)實(shí)例代碼講解Spring?Boot實(shí)現(xiàn)IP限流的相關(guān)操作,感興趣的朋友一起看看吧2025-06-06

