springboot整合elasticsearch 全文检索(高阶API)

文章目录

  • 一、说明:
    • 1.1、小编的案例说明
    • 1.2、对elasticsearch的操作方式种类
  • 二、springboot整合Elasticsearch-Rest-Client
    • 2.1、引入依赖
    • 2.2、设置配置文件
    • 2.3、在测试类中测试 => (添加更新二合一)
    • 2.4、数据检索 => 条件检索
  • 三、如何采用批量插入?
    • 3.1、创建elasticsearch创建映射关系
    • 3.2、java的逻辑代码
  • 四、小结


一、说明:

1.1、小编的案例说明

  1. 如果没有安装可以参考小编这篇文章 ==> 文章入口
  2. 小编的elasticsearch的版本是7.4.2
  3. 案例采用的方式(官方提供的):Elasticsearch-Rest-Client(elasticsearch-rest-high-level-client)
  4. 使用kibana可视化工具查看数据

1.2、对elasticsearch的操作方式种类

  • 操作 ==> 9300端口:TCP

spring-data-elasticsearch:transport-api.jar

说明:springboot 版本不同, transport-api.jar 不同,不能适配 es 版本
7.x 已经不建议使用,8 以后就要废弃

  • 操作 ==> 9200:HTTP
  1. JestClient:非官方,更新慢
  2. RestTemplate:模拟发 HTTP 请求,ES 很多操作需要自己封装,麻烦
  3. HttpClient:同上(简单说就是和elasticsearch关联性不高,都要自己写方法)
  4. Elasticsearch-Rest-Client:官方 RestClient,封装了 ES 操作,API 层次分明,上手简单(推荐)
  5. 使用Elasticsearch-Rest-Client ==>官方文档参考地址
  6. 都在API文档里面,普通的,复杂的检索…
    springboot整合elasticsearch 全文检索(高阶API)_第1张图片

二、springboot整合Elasticsearch-Rest-Client

2.1、引入依赖

小编安装的Elasticsearch版本是7.4.2所以版本要对应依赖版本也要是7.4.2

<!--  elasticsearch-java restful client 操作http  -->
<dependency>
     <groupId>org.elasticsearch.client</groupId>
     <artifactId>elasticsearch-rest-high-level-client</artifactId>
     <version>7.4.2</version>
 </dependency>

要注意的一点是springboot默认会引入spring-data-elasticsearch
所以我们也要将其版本改成和我们对应的版本

如图:
springboot整合elasticsearch 全文检索(高阶API)_第2张图片
在properties里面修改成我们的版本:

 <properties>
    <java.version>1.8</java.version>

      <!-- 这个是spring data 默认支持的。改成和我们自己配置的版本一致-->
      <elasticsearch.version>7.4.2</elasticsearch.version>
  </properties>

查看maven依赖是否保持一致:
springboot整合elasticsearch 全文检索(高阶API)_第3张图片

2.2、设置配置文件

目录:
在这里插入图片描述

package com.atguigu.gulimall.search.config;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author suqinyi
 * @Date 2021/5/23
 */

/**
 * 1、导入依赖
 * 2、编写配置
 * 3、参照API文档
 */
@Configuration
public class GulimallElasticSearchConfig {


    public static final RequestOptions COMMON_OPTIONS;

    static {
        RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
//        builder.addHeader("Authorization", "Bearer " + TOKEN);
//        builder.setHttpAsyncResponseConsumerFactory(
//                new HttpAsyncResponseConsumerFactory
//                        .HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024));
        COMMON_OPTIONS = builder.build();
    }


    //注入client
    @Bean
    public RestHighLevelClient esRestClient() {

        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("192.168.56.10", 9200, "http")
                )
        );
        return client;
    }
}

2.3、在测试类中测试 => (添加更新二合一)

说明:如果在对这个users(名称叫索引)添加数据,那么不会报错,他的版本号会加上去(变化),所以是添加更新二合一

package com.atguigu.gulimall.search;

import com.alibaba.fastjson.JSON;
import com.atguigu.gulimall.search.config.GulimallElasticSearchConfig;
import lombok.Data;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.IOException;

@RunWith(SpringRunner.class)//指定spring的驱动
@SpringBootTest//小编的springboot版本是2.18  说明:2.x和1.x的版本测试类有着区别
public class GulimallSearchApplicationTests {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 测试存储数据到es
     * 更新也可以
     */
    @Test
    public void indexData() throws IOException {
        IndexRequest indexRequest = new IndexRequest("users");
        //数据的id-不设置就自动生成,类型string
        indexRequest.id("1");

        // 方式一:
        //indexRequest.source("username","zhangsan","age",18,"gender","男");

        // 方式二(推荐):
        User user = new User();
        user.setAge(18);
        user.setUsername("zhangsan");
        user.setGender("男");
        String jsonString = JSON.toJSONString(user);
        indexRequest.source(jsonString, XContentType.JSON);

        //调用,执行操作
        IndexResponse index = client.index(indexRequest, GulimallElasticSearchConfig.COMMON_OPTIONS);

        //提取有用的数据
        System.out.println("响应数据:"+"\n"+index);
    }

    @Data//使用lombok插件+依赖
    class User{
        private String username;
        private String gender;
        private Integer age;
    }

    //测试容器是否注入成功
    @Test
    public void testIfOK() {
        System.out.println(client);
    }
}

控制台效果:
springboot整合elasticsearch 全文检索(高阶API)_第4张图片

kibana效果:
springboot整合elasticsearch 全文检索(高阶API)_第5张图片

2.4、数据检索 => 条件检索

更具体的看官方文档示例

 	/**
     *查询-条件检索
     */
    @Test
    public void searchData() throws IOException {
        //创建检索请求
        SearchRequest searchRequest = new SearchRequest();
        //指定索引
        searchRequest.indices("users");

        //指定DSL,检索条件
        //SearchSourceBuilder sourceBuilder 封装检索条件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        //构造检索条件
        sourceBuilder.query(QueryBuilders.matchQuery("username","zhangsan"));
//        sourceBuilder.from();
//        sourceBuilder.size();
//        sourceBuilder.aggregation();//这个是聚合

        System.out.println("检索条件:"+"\n"+sourceBuilder);

        searchRequest.source(sourceBuilder);

        //执行检索
        SearchResponse searchResponse = client.search(searchRequest, GulimallElasticSearchConfig.COMMON_OPTIONS);

        //分析结果
        System.out.println(searchResponse.toString());

        SearchHits hits = searchResponse.getHits();
        SearchHit[] hits1 = hits.getHits();//真正的命中数据--可以进行遍历操作
        for (SearchHit hit : hits1) {
//            System.out.println(hit);
//            System.out.println(hit.xxx);

            //一般要处理的都是source里面的数据 ==> 通常是将其转成string,在和实体类映射起来
            String string = hit.getSourceAsString();
            //利用json工具将string转成实体类:以fastJson为例,jackson也行
            User01 User = JSON.parseObject(string, User01.class);
            System.out.println("user:"+User);
        }
        
        //获取聚合数据--这边小编没准备复杂数据,就没聚合了。这边贴个官方图
    }

    //使用lombok插件+依赖
    @ToString
    @Data
    static class User01{
        private String username;
        private String gender;
        private Integer age;
    }

控制台结果:
在这里插入图片描述
官方的聚合获取操作

官网文档的参考地址==>文档入口
springboot整合elasticsearch 全文检索(高阶API)_第6张图片


三、如何采用批量插入?

在项目中通常的操作

  1. 先在elasticsearch创建映射关系(说白点就是创建索引并且构造数据类型)
  2. 在编写java代码

3.1、创建elasticsearch创建映射关系

说明:
索引是user
里面有userId还有个对象student包含着age和name的字段

所以:在java中创建的实体类的属性名和类型要和这个索引里面的字段对应起来,在操作的时候将实体类转成json,插入es才不会有问题

PUT user
{
	"mappings": {
		"properties": {
			"skuId": {
				"type": "long"
			},
			"student": {
				"type": "nested",
				"properties": {
					"age": {
						"type": "long"
					},
					"name": {
						"type": "keyword"
					}
				}
			}
		}
	}
}

3.2、java的逻辑代码

    //注入
	@Autowired
    RestHighLevelClient restHighLevelClient;

	//业务的核心代码
    @Override
    public boolean saveToEs(List<SkuEsModel> skuEsModels) throws IOException {
     	/**
         * 说明:
         * 传入的List skuEsModels 是一个list
         * 里面有多个SkuEsModel(实体类)和elasticsearch创建的索引(名称和类型)对应
         * 如果不明白。。在看下小编上面写的那个基础整合案例,里面的User
         */
    	
        //保存到es
        //给es中建立索引,user,建立映射关系
        //SkuEsModel这个实体类的属性名和类型和user索引的数据对应起来

        //给es中保存数据
        //源码里面需要的俩个属性:BulkRequest bulkRequest, RequestOptions optionss
        //批量插入
        BulkRequest bulkRequest = new BulkRequest();

		//遍历
        for (SkuEsModel model : skuEsModels) {
            // 构造保存请求
            IndexRequest indexRequest = new IndexRequest(EsConstant.PRODUCT_INDEX);
            //设置id的话可以保证不会加入相同的数据,数据存在会采用更新
            indexRequest.id(model.getSkuId().toString());
            //将数据转成Json。   这边用的是fastjson
            String jsonString = JSON.toJSONString(model);
            indexRequest.source(jsonString, XContentType.JSON);
            bulkRequest.add(indexRequest);
        }

		//restHighLevelClient.bulk()这个采用是同步,里面也有个异步的方法 restHighLevelClient.bulkAsync();
        BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, GulimallElasticSearchConfig.COMMON_OPTIONS);

        // TODO 如果批量错误,待处理问题
        
        // 有错误是true,没有是false
        boolean b = bulk.hasFailures();

		//stream流的写法,看不懂的去看下java8新特性
        List<String> collect = Arrays.stream(bulk.getItems()).map(item -> {
            return item.getId();
        }).collect(Collectors.toList());

        log.info("数据,{},es返回数据{}",collect,bulk.toString());

        return b;
    }

如果有不同意见可以留言评论

四、小结

更加详细的操作看官网文档的示例啦

其实如果安装的是elasticsearch6.x版本
使用spring-data-elasticsearch:transport-api.jar也非常便捷
对于elasticsearch版本的升级要慎重

你可能感兴趣的:(框架整合篇,elasticsearch,版本7.4.2,sprinboot,rest-client)