文章目录
⛄引言
本文参考黑马 分布式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实现搜索、分页
⚡源码编写
定义实体类
实体类有两个,一个是前端的请求参数实体,一个是服务端应该返回的响应结果实体。
importlombok.Data;@DatapublicclassRequestParams{privateString key;privateInteger page;privateInteger size;privateString sortBy;}
定义返回值对象,由于要实现分页,所以需要定义。
import lombok.Data;import java.util.List;
@Data
publicclassPageResult{private Long total;private List<HotelDoc> hotels;publicPageResult(){}publicPageResult(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")publicclassHotelController{@AutowiredprivateIHotelService hotelService;// 搜索酒店数据@PostMapping("/list")publicPageResultsearch(@RequestBodyRequestParams params){return hotelService.search(params);}}
实现搜索业务
我们在controller调用了IHotelService,并没有实现该方法,因此下面我们就在IHotelService中定义方法,并且去实现业务逻辑。
1)在
cn.itcast.hotel.service
中的
IHotelService
接口中定义一个方法:
/**
* 根据关键字搜索酒店信息
* @param params 请求参数对象,包含用户输入的关键字
* @return 酒店文档列表
*/PageResultsearch(RequestParams params);
2)实现搜索业务,肯定离不开RestHighLevelClient,我们需要把它注册到Spring中作为一个Bean。在
项目
中的
HotelDemoApplication
中声明这个Bean:
@BeanpublicRestHighLevelClientclient(){returnnewRestHighLevelClient(RestClient.builder(HttpHost.create("http://IP地址:9200")));}
3)在
service.impl
中的
HotelService
中实现search方法:
@OverridepublicPageResultsearch(RequestParams params){try{// 1.准备RequestSearchRequest request =newSearchRequest("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.解析响应returnhandleResponse(response);}catch(IOException e){thrownewRuntimeException(e);}}// 结果解析privatePageResulthandleResponse(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 =newArrayList<>();for(SearchHit hit : hits){// 获取文档sourceString json = hit.getSourceAsString();// 反序列化HotelDoc hotelDoc = JSON.parseObject(json,HotelDoc.class);// 放入集合
hotels.add(hotelDoc);}// 4.4.封装返回returnnewPageResult(total, hotels);}
二、酒店结果过滤
⌚需求分析
需求: 添加品牌、城市、星级、价格等过滤功能
在页面搜索框下,会有几个过滤条件:
请求参数如下:
包含的过滤条件有:
- brand:品牌值
- city:城市
- minPrice~maxPrice:价格范围
- starName:星级
我们需要做两件事情:
- 修改请求参数的对象RequestParams,接收上述参数
- 修改业务逻辑,在搜索条件之外,添加一些过滤条件
修改实体类
@DatapublicclassRequestParams{privateString key;privateInteger page;privateInteger size;privateString sortBy;// 下面是新增的过滤条件参数privateString city;privateString brand;privateString starName;privateInteger minPrice;privateInteger maxPrice;}
⏰修改搜索业务
在HotelService的search方法中,只有一个地方需要修改:requet.source().query( … )其中的查询条件。
在之前的业务中,只有match查询,根据关键字搜索,现在要添加条件过滤,包括:
- 品牌过滤:是keyword类型,用term查询
- 星级过滤:是keyword类型,用term查询
- 价格过滤:是数值类型,用range查询
- 城市过滤:是keyword类型,用term查询
多个查询条件组合,肯定是boolean查询来组合:
- 关键字搜索放到must中,参与算分
- 其它过滤条件放到filter中,不参与算分
因为条件构建的逻辑比较复杂,这里先封装为一个函数:
buildBasicQuery 函数如下:
privatevoidbuildBasicQuery(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.放入source
request.source().query(boolQuery);}
再次重启运行即可。
✅效果图
⛵小结
以上就是【Bug 终结者】对 Spring Boot 整合 分布式搜索引擎 Elastic Search 实现 搜索、分页与结果过滤 的简单介绍,ES搜索引擎无疑是最优秀的分布式搜索引擎,使用它,可大大提高项目的灵活、高效性!**
技术改变世界!!!
**
如果这篇【文章】有帮助到你,希望可以给【Bug 终结者】点个赞👍,创作不易,如果有对【后端技术】、【前端领域】感兴趣的小可爱,也欢迎关注❤️❤️❤️ 【Bug 终结者】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💝💝💝!
版权归原作者 Bug 终结者 所有, 如有侵权,请联系我们删除。