【Elaticsearch专题】集成springboot的方式之RestClient

在这里插入图片描述

一、Java REST Client介绍

Java Low Level REST Client: 低级别的REST客户端,通过http与集群交互,用户需自己编组请求JSON串,及解析响应JSON串。兼容所有ES版本。
Java High Level REST Client: 高级别的REST客户端,基于低级别的REST客户端,增加了编组请求JSON串、解析响应JSON串等相关api。使用的版本需要保持和ES服务端的版本一致,否则会有版本问题。

二、maven中引入依赖
<dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>6.4.3</version>
        </dependency>

        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>6.4.3</version>
</dependency>
三、Java High Level REST Client 初始化
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ElasticsearchConfig {
    @Value("${restClient.elasticsearch.hostlist}")
    private String hostlist;

    @Bean
    public RestHighLevelClient restHighLevelClient() {
        //解析hostList配置信息
        String[] split = hostlist.split(","); //创建HttpHost数组,其中存放es主机和端口的配置信息
        HttpHost[] httpHostArray = new HttpHost[split.length];
        for (int i = 0; i < split.length; i++) {
            String item = split[i];
            httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")
                    [1]), "http");
        }
        //创建RestHighLevelClient客户端
        return new RestHighLevelClient(RestClient.builder(httpHostArray));
    }

    //项目主要使用RestHighLevelClient,对于低级的客户端暂时不用 @Bean
    public RestClient restClient() {
        //解析hostlist配置信息
        String[] split = hostlist.split(","); //创建HttpHost数组,其中存放es主机和端口的配置信息
        HttpHost[] httpHostArray = new HttpHost[split.length];
        for (int i = 0; i < split.length; i++) {
            String item = split[i];
            httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")
                    [1]), "http");
        }
        return RestClient.builder(httpHostArray).build();
    }
}
四、试用事例
  1. 创建索引
    @Autowired
    private RestHighLevelClient client;
    
    @Test
    public void testCreateIndex() throws IOException {
        //创建索引请求对象
        CreateIndexRequest createIndexRequest = new CreateIndexRequest("hello_es");
        createIndexRequest.settings(Settings.builder().put("number_of_shards", 1)
                .put("number_of_replicas", 0).build());
        createIndexRequest.mapping("doc", "{\n" +
                "\t\"properties\": {\n" +
                "\t\t\"name\": {\n" +
                "\t\t\t\"type\": \"text\"\n" +
                "\t\t},\n" +
                "\t\t\"description\": {\n" +
                "\t\t\t\"type\": \"text\"\n" +
                "\t\t},\n" +
                "\t\t\"studymodel\": {\n" +
                "\t\t\t\"type\": \"keyword\"\n" +
                "\t\t}\n" +
                "\t}\n" +
                "}", XContentType.JSON);
        //创建索引客户端
        IndicesClient indices = client.indices();
        CreateIndexResponse createIndexResponse = indices.create(createIndexRequest,RequestOptions.DEFAULT);
        boolean acknowledged = createIndexResponse.isAcknowledged();
        log.info("isAcknowledged:{}", acknowledged);
    }
  1. 删除索引
@Test
    public void testDeleteIndex() throws IOException {
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("hello_es");
        DeleteIndexResponse deleteIndexResponse = client.indices().delete(deleteIndexRequest);
        boolean acknowledged = deleteIndexResponse.isAcknowledged();
        log.info("isAcknowledged:{}", acknowledged);

    }
  1. 添加文档
@Test
    public void testAddDoc() throws IOException {
        IndexRequest indexRequest = new IndexRequest("hello_es", "doc");
        //一、给json格式
//        indexRequest.source("{\n" +
//                "\t\"name\": \"Bootstrap开发框架\",\n" +
//                "\n" +
//                "\t\"description\": \"Bootstrap是由Twitter推出的一个前台页面开发框架,在行业之中使用较为广泛。此开发框架包含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长页面开发的程序人员)轻松的实现一个不受浏览器限制的 精美界面效果。\",\n" +
//                "\n" +
//                "\t\"studymodel\": \"201001\"\n" +
//                "}", XContentType.JSON);
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("name", "spring cloud实战");
        jsonMap.put("description", "本课程主要从四个章节进行讲解: 1.微服务架构入门 2.spring cloud基础入门3.实战SpringBoot4.注册中心eureka");
        jsonMap.put("studymodel", "201001");
        indexRequest.source(jsonMap);
        client.index(indexRequest, RequestOptions.DEFAULT);
    }
  1. 获取文档
@Test
    public void getDoc() throws IOException {
        GetRequest getRequest = new GetRequest(
                "hello_es",
                "doc",
                "gdbSpW4BXv1xyLWLmtrS");

        //选择返回的字段
        String[] includes = new String[]{"name", "description", "studymodel"};
        String[] excludes = Strings.EMPTY_ARRAY;
        FetchSourceContext fetchSourceContext = new FetchSourceContext(true, includes, excludes);
        getRequest.fetchSourceContext(fetchSourceContext);

        GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);

        Map<String, Object> sourceAsMap = getResponse.getSourceAsMap();
        System.out.println(sourceAsMap);
    }
  1. 更新文档
//更新文档
    @Test
    public void updateDoc() throws IOException {
        UpdateRequest updateRequest = new UpdateRequest("hello_es", "doc",
                "dda3pW4BXv1xyLWLjNpZ");
        Map<String, String> map = new HashMap<>();
        map.put("name", "Spring Cloud实战");
        updateRequest.doc(map);
        UpdateResponse update = client.update(updateRequest, RequestOptions.DEFAULT);
        RestStatus status = update.status();
        System.out.println(status);
    }
  1. 批量插入
@Test
    public void testBulkAdd() throws IOException {
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("name", "spring cloud实战");
        jsonMap.put("description", "本课程主要从四个章节进行讲解: 1.微服务架构入门 2.spring cloud基础入门3.实战SpringBoot4.注册中心eureka");
        jsonMap.put("studymodel", "201001");

        BulkRequest request = new BulkRequest();
        request.add(new IndexRequest("hello_es", "doc")
                .source(jsonMap));
        request.add(new IndexRequest("hello_es", "doc")
                .source(jsonMap));
        request.add(new IndexRequest("hello_es", "doc")
                .source(jsonMap));
        BulkResponse bulkResponse = client.bulk(request, RequestOptions.DEFAULT);
        Stream.of(bulkResponse.getItems()).forEach(model -> log.info("index:{},response:{}",
                model.getIndex(), model.getResponse()));
    }
  1. 查询所有,包含分页以及排序
//查询搜索记录
    @Test
    public void testSearchAll() throws IOException {
        SearchRequest searchRequest = new SearchRequest("hello_es");
        searchRequest.types("doc");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        searchRequest.source(searchSourceBuilder);
        //设置需要显示的字段
        searchSourceBuilder.fetchSource(new String[]{"name", "description", "studymodel"}, Strings.EMPTY_ARRAY);
        //分页查询,设置起始下标,从0开始
        searchSourceBuilder.from(0);
        //每页显示个数
        searchSourceBuilder.size(2);

        //指定排序
        searchSourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
//        searchSourceBuilder.sort(new FieldSortBuilder("name").order(SortOrder.ASC));

        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        Stream.of(searchHits).forEach(model -> {
            String sourceAsString = model.getSourceAsString();
            log.info("sourceAsString:{}", sourceAsString);
        });
    }
  1. 包含查询team query
//Term Query
    @Test
    public void testTermQuery() throws IOException {
        SearchRequest searchRequest = new SearchRequest("hello_es");
        searchRequest.types("doc");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        searchRequest.source(searchSourceBuilder);
        //查询包括spring的结果
        TermQueryBuilder termQueryBuilder = new TermQueryBuilder("name", "spring");
        searchSourceBuilder.query(termQueryBuilder);
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        Stream.of(searchHits).forEach(model -> {
            String sourceAsString = model.getSourceAsString();
            log.info("sourceAsString:{}", sourceAsString);
        });
    }
  1. 根据id精确查询
//根据id精确匹配
    @Test
    public void testQueryId() throws IOException {
        SearchRequest searchRequest = new SearchRequest("hello_es");
        searchRequest.types("doc");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());

        String[] ids = new String[]{"gdbSpW4BXv1xyLWLmtrS"};
        List<String> idList = Arrays.asList(ids);
        searchSourceBuilder.query(QueryBuilders.termsQuery("_id", idList));
        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        Stream.of(searchHits).forEach(model -> {
            String sourceAsString = model.getSourceAsString();
            log.info("sourceAsString:{}", sourceAsString);
        });
    }
  1. match query

match Query即全文检索,它的搜索方式是先将搜索字符串分词,再使用各各词条从索引中搜索。

match query与Term query区别是match query在搜索前先将搜索关键字分词,再拿各各词语去索引中搜索。

下面代码查询流程分析:

1、将“spring开发”分词,分为spring、开发两个词
2、再使用spring和开发两个词去匹配索引中搜索。
3、由于设置了operator为or,只要有一个词匹配成功则就返回该文档。

//matchQuery
    @Test
    public void testMatchQuery() throws IOException {
        SearchRequest searchRequest = new SearchRequest("hello_es");
        searchRequest.types("doc");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        searchSourceBuilder.query(QueryBuilders.matchQuery("name", "spring开发").operator(Operator.OR));
        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        Stream.of(searchHits).forEach(model -> {
            String sourceAsString = model.getSourceAsString();
            log.info("sourceAsString:{}", sourceAsString);
        });
    }
  1. minimum_should_match

上边使用的operator = or表示只要有一个词匹配上就得分,如果实现三个词至少有两个词匹配如何实现? 使用minimum_should_match可以指定文档匹配词的占比。

下面代码查询流程分析:
“spring开发框架”会被分为三个词:spring、开发、框架
设置"minimum_should_match": "80%"表示,三个词在文档的匹配占比为80%,即3*0.8=2.4,向上取整得2,表示至少有两个词在文档中要匹配成功。

@Test
    public void testMinimumShouldMatch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("hello_es");
        searchRequest.types("doc");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        searchSourceBuilder.query(QueryBuilders.matchQuery("description", "基础入门你好").minimumShouldMatch("80%"));
        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        Stream.of(searchHits).forEach(model -> {
            String sourceAsString = model.getSourceAsString();
            log.info("sourceAsString:{}", sourceAsString);
        });
    }
  1. multi Query and boost

单项匹配是在一个field中去匹配,多项匹配是拿关键字去多个Field中匹配,并且给某个字段提高分数

//multi Query and boost
    @Test
    public void testMultiQuery() throws IOException {
        SearchRequest searchRequest = new SearchRequest("hello_es");
        searchRequest.types("doc");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        MultiMatchQueryBuilder multiMatchQueryBuilder =
                QueryBuilders.multiMatchQuery("实战", "description", "name");
        multiMatchQueryBuilder.field("name", 10);
        searchSourceBuilder.query(multiMatchQueryBuilder);
        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        Stream.of(searchHits).forEach(model -> {
            String sourceAsString = model.getSourceAsString();
            log.info("sourceAsString:{}", sourceAsString);
        });
    }
  1. bool query

三个参数:
must:文档必须匹配must所包括的查询条件,相当于 “AND”
should:文档应该匹配should所包括的查询条件其 中的一个或多个,相当于 “OR”
must_not:文档不能匹配must_not所包括的该查询条件,相当于“NOT”

@Test
    public void testBoolQuery() throws IOException {
        SearchRequest searchRequest = new SearchRequest("hello_es");
        searchRequest.types("doc");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        MultiMatchQueryBuilder multiMatchQueryBuilder =
                QueryBuilders.multiMatchQuery("实战", "description", "name");
        multiMatchQueryBuilder.field("name", 10);
        TermQueryBuilder termQueryBuilder = new TermQueryBuilder("studymodel", 201001);
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        boolQueryBuilder.must(termQueryBuilder).must(multiMatchQueryBuilder);
        searchSourceBuilder.query(boolQueryBuilder);

        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        Stream.of(searchHits).forEach(model -> {
            String sourceAsString = model.getSourceAsString();
            log.info("sourceAsString:{}", sourceAsString);
        });
    }
  1. filter

过滤是针对搜索的结果进行过虑,过虑器主要判断的是文档是否匹配,不去计算和判断文档的匹配度得分,所以过虑器性能比查询要高,且方便缓存,推荐尽量使用过虑器去实现查询或者过虑器和查询共同使用。

@Test
    public void testFilter() throws IOException {
        SearchRequest searchRequest = new SearchRequest("hello_es");
        searchRequest.types("doc");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        MultiMatchQueryBuilder multiMatchQueryBuilder =
                QueryBuilders.multiMatchQuery("实战", "description", "name");
        multiMatchQueryBuilder.field("name", 10);
        TermQueryBuilder termQueryBuilder = new TermQueryBuilder("studymodel", 201001);
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        boolQueryBuilder.must(termQueryBuilder).must(multiMatchQueryBuilder);
        searchSourceBuilder.query(boolQueryBuilder);


        boolQueryBuilder.filter(QueryBuilders.termQuery("studymodel", 201001));
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        Stream.of(searchHits).forEach(model -> {
            String sourceAsString = model.getSourceAsString();
            log.info("sourceAsString:{}", sourceAsString);
        });
    }

15、高亮显示

@Test
    public void testHeightLight() throws IOException {
        SearchRequest searchRequest = new SearchRequest("hello_es");
        searchRequest.types("doc");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());

        searchSourceBuilder.fetchSource(new String[]{"name", "description", "studymodel"}, Strings.EMPTY_ARRAY);
        // 设置高亮字段
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.requireFieldMatch(true).field("name")
                .preTags("<strong>").postTags("</strong>");
        searchSourceBuilder.highlighter(highlightBuilder);


        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        Stream.of(searchHits).forEach(model -> {
            String sourceAsString = model.getSourceAsString();
            Map<String, HighlightField> highlightFields = model.getHighlightFields();
            String name = (String) model.getSourceAsMap().get("name");
            if (highlightFields != null) {
                HighlightField nameField = highlightFields.get("name");
                if (nameField != null) {
                    Text[] fragments = nameField.getFragments();
                    StringBuffer stringBuffer = new StringBuffer();
                    for (Text str : fragments) {
                        stringBuffer.append(str.string());
                    }
                    name = stringBuffer.toString();
                }
            }

            log.info("name:{}=====sourceAsString:{}", name, sourceAsString);
        });
    }

以上代码附上github地址: https://github.com/fafeidou/fast-cloud-nacos/tree/master/fast-common-examples/fast-common-es-example/fast-common-es-rest-client-example

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值