首页 > 其他分享 >SpringCloud(七.7)ES(elasticsearch)-- 实战练习

SpringCloud(七.7)ES(elasticsearch)-- 实战练习

时间:2024-04-20 17:24:00浏览次数:17  
标签:String -- SpringCloud private elasticsearch new params public boolQuery

demo地址:链接:https://pan.baidu.com/s/16c1mMcQv7bF3Fcz2X_PE7A   提取码:msvy

库表 tb_hotel.sql : 链接:https://pan.baidu.com/s/1wVdh-fZoyeNbLUkyQYCD5g   提取码:3t4y

 

练习目标一:实现酒店搜索功能,完成关键字搜索和分页功能

 

如图,点击搜索按钮,我们发现它调用的是 hotel/list 接口,且有四个必填入参分别是 key(搜索关键字)、page(当前页码)、size(每页条数)、sortBy(排序字段)

其次根据页面发现还会有其它非必填入参,分别是 city(城市)、starName(星级)、brand(品牌)、minPrice(最低价格)、maxPrice(最高价格)、location(地理位置)

 

1、添加入参实体和返回实体

新增入参实体

@Data
public class RequestParams {
    private String key;
    private Integer page;
    private Integer size;
    private String sortBy;
    private String city;
    private String starName;
    private String brand;
    private Integer minPrice;
    private Integer maxPrice;
    private String location;
}

返回实体(通过页面我们不难发现,只需返回总条数和酒店数据集即可。)

@Data
public class PageResult {
    private Long total;
    private List<HotelDoc> hotels;

    public PageResult() {
    }

    public PageResult(Long total, List<HotelDoc> hotels) {
        this.total = total;
        this.hotels = hotels;
    }
}

 

2、编写Controller

@RestController
@RequestMapping("hotel")
public class HotelController {

    @Autowired
    private IHotelService hotelService;

    @PostMapping("list")
    public PageResult search(@RequestBody RequestParams params) {
        return hotelService.search(params);
    }
}

 

3、在Controller中Alt+Enter生成IHotelService 中的search方法

4、在IHotelService中Alt+Enter生成HotelService中的search实现方法

5、接下来就和上一章 SpringCloud(七.6)ES(elasticsearch)-- RestClient查询文档和结果处理 练习的步骤一致了

  • 准备Request   
  • 准备DSL   
  • 发送请求   
  • 解析响应

但是有个前提,需要准备RestClient,在单元测试中是new出来的。在这里我们应该通过@bean注入到spring容器中。然后在HotleService中就可以@Autowired注入使用了

@Bean
    public RestHighLevelClient restHighLevelClient(){
        return new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.223.129:9200")
        ));
    }

 

现在万事具备就可以编写代码实现功能了。

@Slf4j
@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Override
    public PageResult search(RequestParams params) {
        try {
            // 1.准备Request
            SearchRequest request = new SearchRequest("hotel");
            // 2.准备请求参数
            // 2.1.query
            buildBasicQuery(params, request);
            // 2.2.分页
            int page = params.getPage();
            int size = params.getSize();
            request.source().from((page - 1) * size).size(size);
            // 2.3.距离排序
            String location = params.getLocation();
            if (StringUtils.isNotBlank(location)) {
                request.source().sort(SortBuilders
                        .geoDistanceSort("location", new GeoPoint(location))
                        .order(SortOrder.ASC)
                        .unit(DistanceUnit.KILOMETERS)
                );
            }
            // 3.发送请求
            SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            // 4.解析响应
            return handleResponse(response);
        } catch (IOException e) {
            throw new RuntimeException("搜索数据失败", e);
        }
    }

    private void buildBasicQuery(RequestParams params, SearchRequest request) {
        // 1.准备Boolean查询
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        // 1.1.关键字搜索,match查询,放到must中
        String key = params.getKey();
        if (StringUtils.isNotBlank(key)) {
            // 不为空,根据关键字查询
            boolQuery.must(QueryBuilders.matchQuery("all", key));
        } else {
            // 为空,查询所有
            boolQuery.must(QueryBuilders.matchAllQuery());
        }

        // 1.2.品牌
        String brand = params.getBrand();
        if (StringUtils.isNotBlank(brand)) {
            boolQuery.filter(QueryBuilders.termQuery("brand", brand));
        }
        // 1.3.城市
        String city = params.getCity();
        if (StringUtils.isNotBlank(city)) {
            boolQuery.filter(QueryBuilders.termQuery("city", city));
        }
        // 1.4.星级
        String starName = params.getStarName();
        if (StringUtils.isNotBlank(starName)) {
            boolQuery.filter(QueryBuilders.termQuery("starName", starName));
        }
        // 1.5.价格范围
        Integer minPrice = params.getMinPrice();
        Integer maxPrice = params.getMaxPrice();
        if (minPrice != null && maxPrice != null) {
            maxPrice = maxPrice == 0 ? Integer.MAX_VALUE : maxPrice;
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(minPrice).lte(maxPrice));
        }

        // 2.算分函数查询
        FunctionScoreQueryBuilder functionScoreQuery = QueryBuilders.functionScoreQuery(
                boolQuery, // 原始查询,boolQuery
                new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{ // function数组
                        new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                                QueryBuilders.termQuery("isAD", true), // 过滤条件
                                ScoreFunctionBuilders.weightFactorFunction(10) // 算分函数
                        )
                }
        );

        // 3.设置查询条件
        request.source().query(functionScoreQuery);
    }
  
    private PageResult handleResponse(SearchResponse response) {
        SearchHits searchHits = response.getHits();
        // 4.1.总条数
        long total = searchHits.getTotalHits().value;
        // 4.2.获取文档数组
        SearchHit[] hits = searchHits.getHits();
        // 4.3.遍历
        List<HotelDoc> hotels = new ArrayList<>(hits.length);
        for (SearchHit hit : hits) {
            // 4.4.获取source
            String json = hit.getSourceAsString();
            // 4.5.反序列化,非高亮的
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            // 4.6.处理高亮结果
            // 1)获取高亮map
            Map<String, HighlightField> map = hit.getHighlightFields();
            if (map != null && !map.isEmpty()) {
                // 2)根据字段名,获取高亮结果
                HighlightField highlightField = map.get("name");
                if (highlightField != null) {
                    // 3)获取高亮结果字符串数组中的第1个元素
                    String hName = highlightField.getFragments()[0].toString();
                    // 4)把高亮结果放到HotelDoc中
                    hotelDoc.setName(hName);
                }
            }
            // 4.8.排序信息
            Object[] sortValues = hit.getSortValues();
            if (sortValues.length > 0) {
                hotelDoc.setDistance(sortValues[0]);
            }

            // 4.9.放入集合
            hotels.add(hotelDoc);
        }
        return new PageResult(total, hotels);
    }
}

效果展示:

 

标签:String,--,SpringCloud,private,elasticsearch,new,params,public,boolQuery
From: https://www.cnblogs.com/JoeYD/p/18147510

相关文章

  • Word查找替换通配符(软件著作权用代码文档需求)
    在提交软件著作权所需的代码文档时,需要去掉空行、注释等无关内容,使用Word可以很方便的处理:1、查找//开头的注释,并删除:勾选:通配符,查找://*^13,替换为:^p2、查找/*开头,*/结尾的注释,并删除:勾选:通配符,查找:(/\*)*(\*/),替换为:空3、查找包含制表符的多个空行,并删除:勾选:通配符,查找:(^13)^t......
  • 字符数字分离
    问题:单元格中字符数字如何分离并进行运算 函数公式解决:=EVALUATE(CONCAT(REGEXP(A2,"[*-9]+")))Regexp正则表达式公式提取出从*到数字9之间的字符串,并且让原本连续的字符串在同一个单元格中结果用Concat函数合并,再用Evaluate函数进行运算。 以上公式不适用Microsoft......
  • 14-传输文件
    14.3使用FTP14.3.3使用ftp命令要使用ftp命令连接服务器,只要在这个命令后面跟上服务器名或者IP地址就可以了。ftp10.171.37.1常用的ftp客户端命令命令说明!<commmand>在本地端执行命令?<command>显示ftp命令的帮助信息open连接FTP服务器close或di......
  • 菜品分类
    新增菜品  文件上传    springboot可以自动转换,不使用横线风格也算对思路:定义配置属性类读取yml中的配置项,然后把这个配置类注入到容器,这个对象就封装好了数据然后定义工具类AliossUtils,这个工具类的方法就是获取已上传图片在阿里云服务器中存储的url要使......
  • 网络流问题
    1.网络最大流1.1容量网络和网络最大流 1.1.1容量网络设G(V,E)是一个有向网络,在V中指定了一个顶点,称为源点(记为Vs),以及另一个顶点,称为汇点(记为Vt);对于每一条弧<u,v>∈E,对应有一个权值c(u,v)>0,称为弧的容量(capacity)。通常把这样的有向网络G称为容量网络。 1.1.2弧......
  • 回归问题求解 python---梯度下降+最小二乘法
      MSE=1/m*∑i=1m(yi−y^i)2 a=[1.,2.,3.,4.,5.,6.,7.,8.,9.]b=[3.,5.,7.,9.,11.,13.,15.,17.,19.]points=[[a[i],b[i]]foriinrange(len(a))]lr=0.001eps=0.0001m=len(......
  • 防抖和节流的实现
    防抖和节流在前端开发中是一种非常常见的需求,它们主要用于限制函数的执行频率,优化性能。下面将介绍防抖和节流的实现过程1.防抖防抖是指在事件被触发n秒后再执行回调函数,如果在这n秒内又被重新触发,则重新计算执行时间。简单来说,就是如果持续触发事件,那么回调函数只会在停止触发n......
  • 《算法竞赛进阶指南》 第六章 291. 蒙德里安的梦想 状态压缩DP
    https://www.acwing.com/problem/content/293/求把N×M的棋盘分割成若干个1×2的长方形,有多少种方案。例如当N=2,M=4时,共有5种方案。当N=2,M=3时,共有3种方案。如下图所示:输入格式输入包含多组测试用例。每组测试用例占一行,包含两个整数N和M。当输入用例N=0......
  • MBR1040FCT-ASEMI超低VF值肖特基MBR1040FCT
    编辑:llMBR1040FCT-ASEMI超低VF值肖特基MBR1040FCT型号:MBR1040FCT品牌:ASEMI封装:TO-220F最大平均正向电流(IF):10A最大循环峰值反向电压(VRRM):40V最大正向电压(VF):0.54V~0.70V工作温度:-65°C~175°C反向恢复时间:5ns芯片个数:2芯片尺寸:74mil正向浪涌电流(IFMS):150AMBR1040FCT特性:......
  • js,php,C++ 压缩算法不一致
    参考:https://yushuangqi.com/blog/2015/golang-php-gzencode-difrent.html压缩的数据:这是要压缩的数据aaaaaaaaaaaaaaaaaaa2222222222222222222222222222222顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶fffffffffffffffffffgggggggggggggggggggeeeeeeeeeeeeee对应的三种语言的最后数......