0


SpringBoot集成Elasticsearch8.x(7)|(新版本Java API Client使用完整示例)

SpringBoot集成Elasticsearch8.x(7)|(新版本Java API Client使用完整示例)


文章目录

章节
第一章链接: 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使用完整示例)

前言

在Es7.15版本之后,es官方将它的高级客户端RestHighLevelClient标记为弃用状态。同时推出了全新的java API客户端Elasticsearch Java API Client,该客户端也将在Elasticsearch8.0及以后版本中成为官方推荐使用的客户端。

一、项目依赖

这里没有应用springboot版本自带elasticsearch依赖,自带的版本应该是7.x的,所以单独引入了elasticsearch8.x依赖

<!--   springboot 依赖     --><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.7</version><relativePath/></parent><!--   elasticsearch依赖     --><dependency><groupId>co.elastic.clients</groupId><artifactId>elasticsearch-java</artifactId><version>8.1.0</version></dependency><dependency><groupId>org.glassfish</groupId><artifactId>jakarta.json</artifactId><version>2.0.1</version></dependency>

二、springboot集成实现

1.ElasticSearchConfig配置实现

注入elasticsearch客户端

  @Configuration
public class ElasticSearchConfig {

    @Value("${es.host}")
    private String host;

    @Value("${es.port}")
    private int port;

    @Bean
    public ElasticsearchClient elasticsearchClient(){
        RestClient client = RestClient.builder(new HttpHost(host, port,"http")).build();
        ElasticsearchTransport transport = new RestClientTransport(client, new JacksonJsonpMapper());return new ElasticsearchClient(transport);}}

2.elasticsearch工具类

ElasticsearchHandle工具类主要是封装elasticsearch的索引,数据对应的一些增删改查方法

@Slf4j
@Component
public 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<String, Property> mapping) throws IOException {
        CreateIndexResponse createIndexResponse = client.indices().create(c ->{
            c.index(indexName).mappings(mappings -> mappings.properties(mapping));return c;});return createIndexResponse.acknowledged();}//    public Map<String, Property> buildMapping( Map<String, String> propertyKeys) {//        Map<String, Property> documentMap = new HashMap<>();//        for (Map.Entry<String, String> 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 voidreCreateIndex(String indexName, Map<String, Property> 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<DocumentPartESDto>searchDocument(String indexName, String id){

        try {
            GetResponse<DocumentPartESDto> 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
@AllArgsConstructor
public 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<DocumentParagraph>search(String indexName, String query,int top){
        List<DocumentParagraph> documentParagraphs = Lists.newArrayList();
        try {
            SearchResponse<DocumentParagraph> 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<DocumentParagraph> 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<DocumentParagraph>search(String indexName, String query, List<String> categoryId,int top){
        List<DocumentParagraph> documentParagraphs = Lists.newArrayList();
        List<FieldValue> 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<DocumentParagraph> 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("<em>").postTags("</em>"))).from(0).size(top), DocumentParagraph.class
            );for(Hit<DocumentParagraph> 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<DocumentParagraph> hit){
        DocumentParagraph paragraph = hit.source();
        try {
            Map<String, List<String>> highlight = hit.highlight();
            List<String> 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<String, List<String>> highlight = hit.highlight();
            List<String> list = highlight.get("content");
            String join = StringUtils.join(list,"");if(StringUtils.isNotBlank(join)){
                paragraph.setContent(join);}

4.3.查询某个文档的数据并高亮显示关键词

参数介绍
ndexName:为索引名称
id:文档id

  public List<DocumentParagraph>searchDocumentByDocId(String indexName, String id){
        List<DocumentParagraph> documentParagraphs = Lists.newArrayList();
        try {
            SearchResponse<DocumentParagraph> search = client.search(s -> s
                    .index(indexName).query(q -> q
                            .term(t -> t
                                    .field("docId").value(id))), DocumentParagraph.class
            );for(Hit<DocumentParagraph> 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;}

5.elasticsearch增删工具类

批量增删也是常见类型

5.1.批量增加数据

参数介绍
ndexName:为索引名称
objs:插入实体

     public boolean batchInsertDocument(String indexName, List<DocumentParagraph> objs){
        try {
            List<BulkOperation> 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<DocumentPartESDto> 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 voidcreateIndexAndMapping(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());}}}

总结

以上就是SpringBoot集成Elasticsearch数据库内容,项目已经经过测试,主要类全部都在上面。大家可以参考


本文转载自: https://blog.csdn.net/Oaklkm/article/details/130992152
版权归原作者 Oak科技 所有, 如有侵权,请联系我们删除。

“SpringBoot集成Elasticsearch8.x(7)|(新版本Java API Client使用完整示例)”的评论:

还没有评论