Elasticsearch结合springboot实现搜索功能

本文介绍了如何在SpringBoot项目中使用Elasticsearch进行各种搜索操作,包括全匹配、模糊匹配、多字段匹配、精确查询、范围查询、地理位置查询、布尔查询、排序、分页、高亮和根据相关度评分的函数查询,以及如何配置和使用RestHighLevelClient进行API调用。
摘要由CSDN通过智能技术生成

Elasticsearch可以通过对doc文档的操作实现对不同条件下的搜索,排序,打分等等功能,这个功能不仅可以用dsl语句在控制台的里实现,也可以使用springboot提供的api用java代码实现。

1 事先准备

1.1导入相关依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>

1.2配置环境

spring:
  elasticsearch:
    rest:
      uris: 192.168.184.100:9200 #输入你部署好的es服务地址
  data:
    elasticsearch:
      repositories:
        enabled: true

为了在后面代码中更好使用es工具,我们通过配置类将RestHighLevelClient添加到spring容器中管理。

    @Value("${spring.elasticsearch.rest.uris}")
    private String uris;

    @Bean
    public RestHighLevelClient elasticsearchClient() {
        ClientConfiguration configuration = ClientConfiguration.builder()
                .connectedTo(uris)
                .build();
        return RestClients.create(configuration).rest();
    }

2 代码编写

2.1查询所有

 @Test
    public void MatchAllTest() throws IOException {
        //构建查询request对象
        SearchRequest searchRequest = new SearchRequest("hotel1");
        //查询条件
        searchRequest.source().query(QueryBuilders.matchAllQuery());
        //发起查询
        SearchResponse res = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //结果展示
        showRes(res);
    }

我将结果处理抽取出来进行单独处理

public void showRes(SearchResponse res){
        SearchHits hits = res.getHits();
        int length = (int) hits.getTotalHits().value;
        System.out.println("共查询到 "+length+" 条数据");
        //获取所有查询数据
        SearchHit[] hits1 = hits.getHits();
        for (SearchHit documentFields : hits1) {
            //将doc转为Object对象
            String sourceAsString = documentFields.getSourceAsString();
            Map<String, HighlightField> highlightFields = documentFields.getHighlightFields();
            HotelDoc hotelDoc = JSON.parseObject(sourceAsString, HotelDoc.class);
            //高亮显示搜索内容
            if(!CollectionUtils.isEmpty(highlightFields)){
                HighlightField highlightField = highlightFields.get("name");
                Text[] fragments = highlightField.getFragments();
                String s = fragments[0].toString();
                hotelDoc.setName(s);
            }
            System.out.println(hotelDoc);
        }
    }

其他查询也都大差不差,这里全部贴上代码:

 /**
     * match模糊匹配
     * @throws IOException
     */
    @Test
    public void MatchTest() throws IOException {
        //构建查询request对象
        SearchRequest searchRequest = new SearchRequest("hotel1");
        //查询条件
        searchRequest.source().query(QueryBuilders.matchQuery("name","如家"));
        //发起查询
        SearchResponse res = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //结果展示
        showRes(res);
    }

    /**
     * multi_match 会匹配多个字段信
     * @throws IOException
     */
    @Test
    public void MultiMatchTest() throws IOException {
        //构建查询request对象
        SearchRequest searchRequest = new SearchRequest("hotel1");
        //查询条件
        searchRequest.source().query(QueryBuilders.multiMatchQuery("外滩如家酒店","brand","name","business"));
        //发起查询
        SearchResponse res = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //结果展示
        showRes(res);
    }

    /**
     * term精确查询,必须与传入的值完全相同才能匹配成功
     * @throws IOException
     */
    @Test
    public void TermTest() throws IOException {
        //构建查询request对象
        SearchRequest searchRequest = new SearchRequest("hotel1");
        //查询条件
        searchRequest.source().query(QueryBuilders.termQuery("id","434082"));
        //发起查询
        SearchResponse res = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //结果展示
        showRes(res);
    }

    /**
     * range范围查询
     * @throws IOException
     */
    @Test
    public void rangeTest() throws IOException {
        //构建查询request对象
        SearchRequest searchRequest = new SearchRequest("hotel1");
        //查询条件
        searchRequest.source().query(QueryBuilders.rangeQuery("score").gt(10).lt(30));
        //发起查询
        SearchResponse res = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //结果展示
        showRes(res);
    }

    //distance查询地理位置
    @Test
    public void distanceTest() throws IOException {
        //构建查询request对象
        SearchRequest searchRequest = new SearchRequest("hotel1");
        //查询条件
        searchRequest.source().query(QueryBuilders
                .geoDistanceQuery("location") //具体根据什么信息查询
                .distance("3km") //查询范围
                .point(31.220706,121.498769)); //范围中心坐标
        //发起查询
        SearchResponse res = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //结果展示
        showRes(res);
    }
 //复合查询 boolean
    @Test
    public void boolTest() throws IOException {
        //构建查询request对象
        SearchRequest searchRequest = new SearchRequest("hotel1");
        //查询条件
        searchRequest.source().query(QueryBuilders.boolQuery()
                .must(QueryBuilders.matchQuery("name","如家"))
                .filter(QueryBuilders.rangeQuery("price").lt(300))
                .should(QueryBuilders.termQuery("city","北京"))
        );
        //发起查询
        SearchResponse res = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //结果展示
        showRes(res);
    }
//排序和分页
    @Test
    public void SortAndPageTest() throws IOException {
        int page = 1;int size = 5;
        //构建查询request对象
        SearchRequest searchRequest = new SearchRequest("hotel1");
        //查询条件
        searchRequest.source().query(QueryBuilders.matchAllQuery());
        searchRequest.source().size(size).from((page-1)*size);
        searchRequest.source().sort("price", SortOrder.ASC);
        //发起查询
        SearchResponse res = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //结果展示
        showRes(res);
    }

    /**
     * 高亮搜索内容
     * @throws IOException
     */
    @Test
    public void HighlightTest() throws IOException {
        //构建查询request对象
        SearchRequest searchRequest = new SearchRequest("hotel1");
        //查询条件
        searchRequest.source().query(QueryBuilders.matchQuery("all","如家酒店"));
        searchRequest.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));
        //发起查询
        SearchResponse res = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //结果展示
        showRes(res);
    }

对结果相关度算分后重新排序这个稍微复杂点,单独列出来:

/**
     * 根据相关度算分排序
     * @throws IOException
     */
    @Test
    public void functionScoreTest() throws IOException {
        //构建查询request对象
        SearchRequest searchRequest = new SearchRequest("hotel1");
        //基础查询条件
        MatchAllQueryBuilder matchAllQuery = QueryBuilders.matchAllQuery();
        //算分查询
        FunctionScoreQueryBuilder functionScoreQuery = QueryBuilders.functionScoreQuery(
                matchAllQuery, //基础查询
                new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{ //算分函数
                    new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                            QueryBuilders.termQuery("isAD",true), //筛选算分条件
                            ScoreFunctionBuilders.weightFactorFunction(10)  //算分方式
                    )
                }).boostMode(CombineFunction.SUM); //对是广告的查询结果加10分
        //查询条件
        searchRequest.source().query(functionScoreQuery);
        //发起查询
        SearchResponse res = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //结果展示
        showRes(res);
    }

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值