行业知识
SpringBoot集成Elasticsearch8.x(7)|(新版本Java API Client使用完整示例)
SpringBoot集成Elasticsearch8.x(7)|(新版本Java API Client使用完整示例)
文章目录
- SpringBoot集成Elasticsearch8.x(7)|(新版本Java API Client使用完整示例)
- @[TOC]
- 前言
- 一、项目依赖
- 二、springboot集成实现
- 1.ElasticSearchConfig配置实现
- 2.elasticsearch工具类
- 3.定义一个ES存储数据结构体
- 4.elasticsearch查询工具类
- 4.1.查询满足条件的数据
- 4.2.查询某些分组下满足条件的数据
- 4.3.查询某个文档的数据并高亮显示关键词
- 4.4.查询多条件OR匹配查询
- 5.elasticsearch增删工具类
- 5.1.批量增加数据
- 5.2.批量删除数据
- 5.调用测试实现
- 总结
- @[TOC]
- 前言
- 一、项目依赖
- 二、springboot集成实现
- 1.ElasticSearchConfig配置实现
- 2.elasticsearch工具类
- 3.定义一个ES存储数据结构体
- 4.elasticsearch查询工具类
- 4.1.查询满足条件的数据
- 4.2.查询某些分组下满足条件的数据
- 4.3.查询某个文档的数据并高亮显示关键词
- 4.4.查询多条件OR匹配查询
- 5.elasticsearch增删工具类
- 5.1.批量增加数据
- 5.2.批量删除数据
- 5.调用测试实现
- 总结
���节
()第一章链接: SpringBoot集成Elasticsearch7.x(1)|(增删改查功能实现)
第二章链接: SpringBoot集成Elasticsearch7.x(2)|(复杂查询)
()第三章链接: SpringBoot集成Elasticsearch7.x(3)|(aggregations之指标聚合查询)
第四章链接: SpringBoot集成Elasticsearch7.x(4)|(aggregations之分桶聚合查询)
第五章链接: SpringBoot集成Elasticsearch7.x(5)|(term、match、match_phrase区别)
第六章链接: SpringBoot集成Elasticsearch8.x(6)|(新版本Java API Client使用)
第七章链接: SpringBoot集成Elasticsearch8.x(7)|(新版本Java API Client使用完整示例)
第八章链接:SpringBoot集成Elasticsearch8.x(8)|(新版本Java API Client的Painless语言脚本script使用)
前言
在Es7.15版本之后,es官方将它的高级客户端RestHighLevelClient标记为弃用状态。同时推出了全新的java API客户端Elasticsearch Java API Client,该客户端也将在Elasticsearch8.0及以后版本中成为官方推荐使用的客户端。
一、项目依赖
这里没有应用springboot版本自带elasticsearch依赖,自带的版本应该是7.x的,所以单独引入了elasticsearch8.x依赖
org.springframework.boot spring-boot-starter-parent 2.5.7 co.elastic.clients elasticsearch-java 8.1.0 org.glassfish jakarta.json 2.0.1
二、springboot集成实现
1.ElasticSearchConfig配置实现
注入elasticsearch客户端,此处兼容了es的集群模式配置格式http://ip1:9200、http://ip2:9200
@Configurationpublic class ElasticSearchConfig { @Value("${es.hosts}") private String hosts; @Value("${es.name:elastic}") private String name; @Value("${es.password:aimind}") private String password; @Bean public ElasticsearchClient docqaElasticsearchClient() { final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(name, password)); List httpHosts = Lists.newArrayList(); String[] split = hosts.split(","); for (int i = 0; i httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider).setKeepAliveStrategy((response, context) -> 180 * 1000)) .build(); ElasticsearchTransport transport = new RestClientTransport(client, new JacksonJsonpMapper()); return new ElasticsearchClient(transport); }} 2.elasticsearch工具类
ElasticsearchHandle工具类主要是封装elasticsearch的索引,数据对应的一些增删改查方法
@Slf4j@Componentpublic class ElasticsearchHandle { @Autowired private ElasticsearchClient client; /** * 判断索引是否存在 * * @param indexName * @return * @throws IOException */ public boolean hasIndex(String indexName) throws IOException { BooleanResponse exists = client.indices().exists(d -> d.index(indexName)); return exists.value(); } /** * 删除索引 * * @param indexName * @throws IOException */ public boolean deleteIndex(String indexName) throws IOException { DeleteIndexResponse response = client.indices().delete(d -> d.index(indexName)); return true; } /** * 创建索引 * * @param indexName * @return * @throws IOException */ public boolean createIndex(String indexName) { try { CreateIndexResponse indexResponse = client.indices().create(c -> c.index(indexName)); } catch (IOException e) { log.error("索引创建失败:{}", e.getMessage()); throw new ExploException(HttpCode.INDEX_CREATE_ERROR, "创建索引失败"); } return true; } /** * 创建索引,不允许外部直接调用 * * @param indexName * @param mapping * @throws IOException */ private boolean createIndex(String indexName, Map mapping) throws IOException { CreateIndexResponse createIndexResponse = client.indices().create(c -> { c.index(indexName).mappings(mappings -> mappings.properties(mapping)); return c; }); return createIndexResponse.acknowledged(); }// public Map buildMapping( Map propertyKeys) {// Map documentMap = new HashMap();// for (Map.Entry propertyKey : propertyKeys.entrySet()) {// String type = getIndxPropType(propertyKey.getValue());// String key = propertyKey.getKey();// log.info("属性:{}类型:{}", key, type);// if (type.equals("text")) {// documentMap.put(key, Property.of(property ->// property.keyword(KeywordProperty.of(p ->// p.index(true)// )// )// )// );// } else if (type.equals("date")) {// documentMap.put(key, Property.of(property ->// property.date(DateProperty.of(p ->// p.index(true).format("yyyy-MM-dd HH:mm:ss.SSS")// )// )// )// );// } else if (type.equals("long")) {// documentMap.put(key, Property.of(property ->// property.long_(LongNumberProperty.of(p ->// p.index(true)// )// )// )// );// } else if (type.equals("integer")) {// documentMap.put(key, Property.of(property ->// property.integer(// IntegerNumberProperty.of(p ->// p.index(false)// )// )// )// );// } else {// documentMap.put(key, Property.of(property ->// property.object(// ObjectProperty.of(p ->// p.enabled(true)// )// )// )// );// }// }// return documentMap;// } /** * 重新创建索引,如果已存在先删除 * * @param indexName * @param mapping */ public void reCreateIndex(String indexName, Map mapping) { try { if (this.hasIndex(indexName)) { this.deleteIndex(indexName); } } catch (IOException e) { e.printStackTrace(); throw new ExploException(HttpCode.INDEX_DELETE_ERROR, "删除索引失败"); } try { this.createIndex(indexName, mapping); } catch (IOException e) { e.printStackTrace(); throw new ExploException(HttpCode.INDEX_CREATE_ERROR, "重新创建索引失败"); } } /** * 新增数据 * * @param indexName * @throws IOException */ public boolean insertDocument(String indexName, Object obj, String id) { try { IndexResponse indexResponse = client.index(i -> i .index(indexName) .id(id) .document(obj)); return true; } catch (IOException e) { log.error("数据插入ES异常:{}", e.getMessage()); throw new ExploException(HttpCode.ES_INSERT_ERROR, "ES新增数据失败"); } } /** * 查询数据 * * @param indexName * @param id * @return */ public GetResponse searchDocument(String indexName, String id) { try { GetResponse getResponse = client.get(g -> g .index(indexName) .id(id) , DocumentPartESDto.class ); return getResponse; } catch (IOException e) { log.error("查询ES异常:{}", e.getMessage()); throw new ExploException(HttpCode.ES_SEARCH_ERROR, "查询ES数据失败"); } } /** * 删除数据 * * @param indexName * @param id * @return */ public boolean deleteDocument(String indexName, String id) { try { DeleteResponse deleteResponse = client.delete(d -> d .index(indexName) .id(id) ); } catch (IOException e) { log.error("删除Es数据异常:{}", e.getMessage()); throw new ExploException(HttpCode.ES_DELETE_ERROR, "数据删除失败"); } return true; }} 3.定义一个ES存储数据结构体
定义一个实体,用于向ES中存储数据
@Data@Builder@NoArgsConstructor@AllArgsConstructorpublic class DocumentPartESDto { private String id; private String docId; private String kgId; private String content; private String type;} 4.elasticsearch查询工具类
由于我们使用大多情况是查询的场景,这里我来完善查询的一些方法
4.1.查询满足条件的数据
参数介绍
ndexName:为索引名称
query:查询的内容
top :查询条数
public List search(String indexName, String query,int top) { List documentParagraphs = Lists.newArrayList(); try { SearchResponse search = client.search(s -> s .index(indexName) .query(q -> q .match(t -> t .field("content") .query(query) )) .from(0) .size(top)// .sort(f -> f.field(o -> o.field("docId").order(SortOrder.Desc))) , DocumentParagraph.class ); for (Hit hit : search.hits().hits()) { DocumentParagraph pd = hit.source(); documentParagraphs.add(pd); } } catch (IOException e) { log.error("查询ES异常:{}", e.getMessage()); throw new ExploException(HttpCode.ES_SEARCH_ERROR, "查询ES数据失败"); } return documentParagraphs; } 4.2.查询某些分组下满足条件的数据
参数介绍
ndexName:为索引名称
query:查询的内容
categoryId: 查询那些类别下的数据
top :查询条数
public List search(String indexName, String query, List categoryId,int top) { List documentParagraphs = Lists.newArrayList(); List values = new ArrayList(); for (String id : categoryId) { values.add(FieldValue.of(id)); } Query categoryQuery = TermsQuery.of(t -> t.field("categoryId.keyword").terms(new TermsQueryField.Builder() .value(values).build() ))._toQuery(); try { SearchResponse search = client.search(s -> s .index(indexName) .query(q -> q .bool(b -> b .must(categoryQuery ) .should(sh -> sh .match(t -> t .field("content") .query(query) ) ) ) ) .highlight(h -> h .fields("content", f -> f .preTags("") .postTags("") ) ) .from(0) .size(top) , DocumentParagraph.class ); for (Hit hit : search.hits().hits()) { DocumentParagraph pd = hit.source(); documentParagraphs.add(pd); } } catch (IOException e) { log.error("查询ES异常:{}", e.getMessage()); throw new ExploException(HttpCode.ES_SEARCH_ERROR, "查询ES数据失败"); } return documentParagraphs; }/*** 高亮数据提取*/ private DocumentParagraph highLight(Hit hit) { DocumentParagraph paragraph = hit.source(); try { Map highlight = hit.highlight(); List list = highlight.get("content"); String join = StringUtils.join(list, ""); if (StringUtils.isNotBlank(join)) { paragraph.setContent(join); paragraph.setScore(hit.score()); } } catch (Exception e) { log.error("获取ES高亮数据异常:{}", e.getMessage()); } return paragraph; }/***解析高亮数据*/ Map highlight = hit.highlight(); List list = highlight.get("content"); String join = StringUtils.join(list, ""); if (StringUtils.isNotBlank(join)) { paragraph.setContent(join); } 4.3.查询某个文档的数据并高亮显示关键词
参数介绍
ndexName:为索引名称
id:文档id
public List searchDocumentByDocId(String indexName, String id) { List documentParagraphs = Lists.newArrayList(); try { SearchResponse search = client.search(s -> s .index(indexName) .query(q -> q .term(t -> t .field("docId") .value(id) ) ), DocumentParagraph.class ); for (Hit hit : search.hits().hits()) { DocumentParagraph pd = hit.source(); documentParagraphs.add(pd); } } catch (IOException e) { log.error("查询ES异常:{}", e.getMessage()); throw new ExploException(HttpCode.ES_SEARCH_ERROR, "查询ES数据失败"); } return documentParagraphs; } 4.4.查询多条件OR匹配查询
参数介绍
docNo:文档编号
docTitle:文档标题
docContext:文档内容
输入参数:query
实现查询上述字段中含有query关键词操作,
类似于: docNo like query or docTitlelike query or docContextlike query
List list = Lists.newArrayList(); list.add(MatchQuery.of(t -> t.field("docNo").query(query).boost(1.2F))._toQuery()); list.add(MatchQuery.of(t -> t.field(" docTitle ").query(query).boost(1.5F))._toQuery()); list.add(MatchQuery.of(t -> t.field("docContext ").query(query).boost(1.8F))._toQuery()); try { SearchResponse search = client.search(s -> s .index(indexName) .query(q -> q .bool(b -> b .should(list) ) ) .from(0) .size(top) , DocumentParagraph.class ); 5.elasticsearch增删工具类
批量增删也是常见类型
5.1.批量增加数据
参数介绍
ndexName:为索引名称
objs:插入实体
public boolean batchInsertDocument(String indexName, List objs) { try { List bulkOperationArrayList = new ArrayList(); for (DocumentParagraph obj : objs) { bulkOperationArrayList.add(BulkOperation.of(o -> o.index(i -> i.document(obj)))); } BulkResponse bulkResponse = client.bulk(b -> b.index(indexName).operations(bulkOperationArrayList)); return true; } catch (IOException e) { log.error("数据插入ES异常:{}", e.getMessage()); throw new ExploException(HttpCode.ES_INSERT_ERROR, "ES新增数据失败"); } } 5.2.批量删除数据
删除文章下的所有数据
参数介绍
ndexName:为索引名称
docId:文章id
public Boolean deleteDocument(String indexName, String docId) { try { client.deleteByQuery(d -> d .index(indexName) .query(q -> q .term(t -> t .field("docId") .value(docId) ) ) ); } catch (IOException e) { log.error("查询ES异常:{}", e.getMessage()); } return true; } 5.调用测试实现
实现索引的创建以及数据的存储查询示例
@Api(tags = {"ES操作"})@RestController@RequestMapping("/es")public class TestEsCurdCtrl { @Autowired public ElasticsearchHandle elasticsearchHandle; @ApiOperation(value = "添加es文件", notes = "添加es文件") @GetMapping(value = "/add") public ResponseHandle deleteDocument(@RequestParam(value = "id") String id) { DocumentPartESDto doc = DocumentPartESDto.builder() .id(id) .docId(id) .content("这是文本内容" + id) .type("doc") .build(); elasticsearchHandle.insertDocument("doc", doc, id); return ResponseHandle.SUCCESS("成功"); } @ApiOperation(value = "查询es文件", notes = "查询es文件") @GetMapping(value = "/search") public ResponseHandle searchDocument(@RequestParam(value = "id") String id) { GetResponse doc = elasticsearchHandle.searchDocument("doc", id); DocumentPartESDto docDto = doc.source(); return ResponseHandle.SUCCESS(docDto); } @ApiOperation(value = "创建索引", notes = "创建索引") @GetMapping(value = "/index") public ResponseHandle createIndex(@RequestParam(value = "indexName") String indexName) { elasticsearchHandle.createIndex(indexName); return ResponseHandle.SUCCESS("成功"); } /** * 创建mapping索引 * * @param indexName */ public static String esmappingV2 = "{\"properties\":{\"docId\":{\"type\":\"keyword\"},\"docName\":{\"type\":\"text\",\"analyzer\":\"ik_max_word\",\"search_analyzer\":\"ik_smart\",\"copy_to\":\"all\"},\"categoryId\":{\"type\":\"keyword\"},\"libVersionList\":{\"type\":\"keyword\"},\"content\":{\"type\":\"text\",\"analyzer\":\"ik_max_word\",\"search_analyzer\":\"ik_smart\",\"copy_to\":\"all\"},\"title\":{\"type\":\"text\",\"analyzer\":\"ik_max_word\",\"search_analyzer\":\"ik_smart\",\"copy_to\":\"all\"},\"all\":{\"type\":\"text\",\"analyzer\":\"ik_max_word\",\"search_analyzer\":\"ik_smart\"}}}"; public void createIndexAndMapping(String indexName) { try { JsonpMapper mapper = client._transport().jsonpMapper(); JsonParser parser = mapper.jsonProvider().createParser(new StringReader(esmappingV2)); client.indices().create(c -> c. index(indexName) .mappings(TypeMapping._DESERIALIZER.deserialize(parser, mapper)) ); } catch (Exception e) { if (StringUtils.contains(e.getMessage(), "resource_already_exists_exception")) { log.warn("索引存在不创建"); return; } log.error("es新增mapping索引异常:{}", e.getMessage()); throw new SkynetException(HttpCode.ES_INDEX_ERROR.code(), HttpCode.ES_INDEX_ERROR.message()); } }} 总结
上一篇:光纤服务器怎么联网使用?
下一篇:真正云服务器怎么用手机?