文章目录
- ⛄引言
- 一、酒店搜索和分页
- ⛅需求分析
- ⚡源码编写
- 二、酒店结果过滤
- ⌚需求分析
- ⏰修改搜索业务
- ✅效果图
- ⛵小结
⛄引言
本文参考黑马 分布式Elastic search
Elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以帮助我们从海量数据中快速找到需要的内容
一、酒店搜索和分页
⛅需求分析
实现黑马旅游的酒店搜索功能,完成关键字搜索和分页
在项目首页,有一个很大的搜索框、也有分页按钮
点击搜索按钮,可以看到浏览器控制台 网络发出了请求
请求参数如下:
{"key": "","page": 1,"size": 5,"sortBy": "default"
}
由此可以知道,我们这个请求的信息如下:
- 请求方式:POST
- 请求路径:/hotel/list
- 请求参数:JSON对象,包含4个字段:
- key:搜索关键字
- page:页码
- size:每页大小
- sortBy:排序,目前暂不实现
- 返回值:分页查询,需要返回分页结果PageResult,包含两个属性:
total
:总条数List<HotelDoc>
:当前页的数据
因此,我们实现业务的流程如下:
- 步骤一:定义实体类,接收请求参数的JSON对象
- 步骤二:编写controller,接收页面的请求
- 步骤三:编写业务实现,利用RestHighLevelClient实现搜索、分页
⚡源码编写
定义实体类
实体类有两个,一个是前端的请求参数实体,一个是服务端应该返回的响应结果实体。
import lombok.Data;@Data
public class RequestParams {private String key;private Integer page;private Integer size;private String sortBy;
}
定义返回值对象,由于要实现分页,所以需要定义。
import lombok.Data;import java.util.List;@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;}
}
定义Controller 控制层
定义一个HotelController,声明查询接口,满足下列要求:
- 请求方式:Post
- 请求路径:/hotel/list
- 请求参数:对象,类型为RequestParam
- 返回值:PageResult,包含两个属性
Long total
:总条数List<HotelDoc> hotels
:酒店数据
@RestController
@RequestMapping("/hotel")
public class HotelController {@Autowiredprivate IHotelService hotelService;// 搜索酒店数据@PostMapping("/list")public PageResult search(@RequestBody RequestParams params){return hotelService.search(params);}
}
实现搜索业务
我们在controller调用了IHotelService,并没有实现该方法,因此下面我们就在IHotelService中定义方法,并且去实现业务逻辑。
1)在cn.itcast.hotel.service
中的IHotelService
接口中定义一个方法:
/*** 根据关键字搜索酒店信息* @param params 请求参数对象,包含用户输入的关键字 * @return 酒店文档列表*/
PageResult search(RequestParams params);
2)实现搜索业务,肯定离不开RestHighLevelClient,我们需要把它注册到Spring中作为一个Bean。在项目
中的HotelDemoApplication
中声明这个Bean:
@Bean
public RestHighLevelClient client(){return new RestHighLevelClient(RestClient.builder(HttpHost.create("http://IP地址:9200")));
}
3)在service.impl
中的HotelService
中实现search方法:
@Override
public PageResult search(RequestParams params) {try {// 1.准备RequestSearchRequest request = new SearchRequest("hotel");// 2.准备DSL// 2.1.queryString key = params.getKey();if (key == null || "".equals(key)) {boolQuery.must(QueryBuilders.matchAllQuery());} else {boolQuery.must(QueryBuilders.matchQuery("all", key));}// 2.2.分页int page = params.getPage();int size = params.getSize();request.source().from((page - 1) * size).size(size);// 3.发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 4.解析响应return handleResponse(response);} catch (IOException e) {throw new RuntimeException(e);}
}// 结果解析
private PageResult handleResponse(SearchResponse response) {// 4.解析响应SearchHits searchHits = response.getHits();// 4.1.获取总条数long total = searchHits.getTotalHits().value;// 4.2.文档数组SearchHit[] hits = searchHits.getHits();// 4.3.遍历List<HotelDoc> hotels = new ArrayList<>();for (SearchHit hit : hits) {// 获取文档sourceString json = hit.getSourceAsString();// 反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);// 放入集合hotels.add(hotelDoc);}// 4.4.封装返回return new PageResult(total, hotels);
}
二、酒店结果过滤
⌚需求分析
需求: 添加品牌、城市、星级、价格等过滤功能
在页面搜索框下,会有几个过滤条件:
请求参数如下:
包含的过滤条件有:
- brand:品牌值
- city:城市
- minPrice~maxPrice:价格范围
- starName:星级
我们需要做两件事情:
- 修改请求参数的对象RequestParams,接收上述参数
- 修改业务逻辑,在搜索条件之外,添加一些过滤条件
修改实体类
@Data
public class RequestParams {private String key;private Integer page;private Integer size;private String sortBy;// 下面是新增的过滤条件参数private String city;private String brand;private String starName;private Integer minPrice;private Integer maxPrice;
}
⏰修改搜索业务
在HotelService的search方法中,只有一个地方需要修改:requet.source().query( … )其中的查询条件。
在之前的业务中,只有match查询,根据关键字搜索,现在要添加条件过滤,包括:
- 品牌过滤:是keyword类型,用term查询
- 星级过滤:是keyword类型,用term查询
- 价格过滤:是数值类型,用range查询
- 城市过滤:是keyword类型,用term查询
多个查询条件组合,肯定是boolean查询来组合:
- 关键字搜索放到must中,参与算分
- 其它过滤条件放到filter中,不参与算分
因为条件构建的逻辑比较复杂,这里先封装为一个函数:
buildBasicQuery 函数如下:
private void buildBasicQuery(RequestParams params, SearchRequest request) {// 1.构建BooleanQueryBoolQueryBuilder boolQuery = QueryBuilders.boolQuery();// 2.关键字搜索String key = params.getKey();if (key == null || "".equals(key)) {boolQuery.must(QueryBuilders.matchAllQuery());} else {boolQuery.must(QueryBuilders.matchQuery("all", key));}// 3.城市条件if (params.getCity() != null && !params.getCity().equals("")) {boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));}// 4.品牌条件if (params.getBrand() != null && !params.getBrand().equals("")) {boolQuery.filter(QueryBuilders.termQuery("brand", params.getBrand()));}// 5.星级条件if (params.getStarName() != null && !params.getStarName().equals("")) {boolQuery.filter(QueryBuilders.termQuery("starName", params.getStarName()));}// 6.价格if (params.getMinPrice() != null && params.getMaxPrice() != null) {boolQuery.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));}// 7.放入sourcerequest.source().query(boolQuery);
}
再次重启运行即可。
✅效果图
⛵小结
以上就是【Bug 终结者】对 Spring Boot 整合 分布式搜索引擎 Elastic Search 实现 搜索、分页与结果过滤 的简单介绍,ES搜索引擎无疑是最优秀的分布式搜索引擎,使用它,可大大提高项目的灵活、高效性! 技术改变世界!!!
如果这篇【文章】有帮助到你,希望可以给【Bug 终结者】点个赞👍,创作不易,如果有对【后端技术】、【前端领域】感兴趣的小可爱,也欢迎关注❤️❤️❤️ 【Bug 终结者】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💝💝💝!