分布式搜索———黑马旅游
创始人
2024-01-20 05:38:45
0

案例功能实现 :

酒店搜索和分页
酒店结果过滤
我周边的酒店
酒店竞价排名

资源链接
hoteld-demo工程:https://pan.baidu.com/s/1YlKz6vxcm7VWXAWPlUiBqg
提取码:GY66

进入hoteld-demo工程,启动服务,打开浏览器进入http://localhost:8089/即可成功访问页面
在这里插入图片描述

案例一: 实现黑马旅游的酒店搜索功能,完成关键字搜索和分页

1、定义实体类,接收前端请求

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 hotelDocs;
}

2、定义controller接口,接收页面请求,调用IHotelService的search方法
① controller接口

public interface IHotelService extends IService {PageResult search(RequestParams params) throws IOException;
}

② web层

@RestController
@RequestMapping("/hotel")
public class HotelController {@Autowiredprivate IHotelService service;@PostMapping("/list")public PageResult search(@RequestBody RequestParams params) throws IOException {return  service.search(params);}
}

3、定义IHotelService中的search方法,利用match查询实现根据关键字搜索酒店信息

@Service
public class HotelService extends ServiceImpl implements IHotelService {@Autowiredprivate RestHighLevelClient client;@Overridepublic PageResult search(RequestParams params) {try {// 1、创建request对象SearchRequest request = new SearchRequest("hotel");// 2、准备DSL//  2.1、 queryString key = params.getKey();if (key == null || "".equals(key)) {request.source().query(QueryBuilders.matchAllQuery());} else {request.source().query(QueryBuilders.matchQuery("all", key));}//  2.2、 分页(利用参数中的page、size实现)int page = params.getPage();int size = params.getSize();request.source().from((page - 1) * size).size(size);// 3、发送请求SearchResponse response = null;response = client.search(request, RequestOptions.DEFAULT);//  解析响应return handleResonse(response);} catch (IOException e) {throw new RuntimeException(e);}}private PageResult handleResonse(SearchResponse response) {// 4、解析响应SearchHits searchHits = response.getHits();long total = searchHits.getTotalHits().value;SearchHit[] hits = searchHits.getHits();// 遍历List hotelDocs = new ArrayList<>();for (SearchHit hit : hits) {String json = hit.getSourceAsString();// 反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);hotelDocs.add(hotelDoc);}// 封装返回return new PageResult(total,hotelDocs);}
}

启动服务,进行测试
在这里插入图片描述

案例二: 添加品牌、城市、星级、价格等过滤功能

1、修改RequestParams类(前端所传的数据),添加brand、city、starName、minPrice、maxPrice等参数

package com.GY.hotel.pojo;import lombok.Data;
@Data
public class RequestParams {// 搜索换关键字private String key;// 当前页码private Integer page;// 分页大小private Integer size;// 排序字段private String sortBy;// 品牌private String brand;// 城市private String city;// 星级private  String starName;// 最低价格private int minPrice;// 最高价格private int maxPrice;
}

2、修改search方法的实现,在match查询基础上添加过滤条件,在关键字搜索时,在如果brand等参数存在,对其做过滤

过滤条件包括:
●  city精确匹配  (term查询)
●  brand精确匹配   (term查询)
●  starName精确匹配    (term查询)
●  price范围过滤     (range查询)
注意事项:
●  多个条件之间是AND关系,组合多条件用BooleanQuery
●  参数存在才需要过滤,做好非空判断
@Service
public class HotelService extends ServiceImpl implements IHotelService {@Autowiredprivate RestHighLevelClient client;@Overridepublic PageResult search(RequestParams params) {// 查询分页try {// 1、创建request对象SearchRequest request = new SearchRequest("hotel");// 2、准备DSL//  2.1、 query// 构建BooleanQuerybuildBasicQuery(params, request);//  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);//  解析响应return handleResponse(response);} catch (IOException e) {throw new RuntimeException(e);}}private void buildBasicQuery(RequestParams params, SearchRequest request) {BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();// 关键字搜索String key = params.getKey();if (key == null || "".equals(key)) {boolQuery.must(QueryBuilders.matchAllQuery());} else {boolQuery.must(QueryBuilders.matchQuery("name", key));}// 城市条件 (term属于过滤条件放在must中会影响得分进而影响查询性能)if(params.getCity()!=null && !params.getCity().equals("")){boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));}// 品牌条件if(params.getBrand()!=null && !params.getBrand().equals("")){boolQuery.filter(QueryBuilders.termQuery("brand", params.getBrand()));}// 星级条件if(params.getStarName()!=null && !params.getStarName().equals("")){boolQuery.filter(QueryBuilders.termQuery("starName", params.getStarName()));}// 价格if(params.getMinPrice()!=null && params.getMaxPrice()!=null){boolQuery.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));}request.source().query(boolQuery);}private PageResult handleResponse(SearchResponse response) {// 4、解析响应SearchHits searchHits = response.getHits();long total = searchHits.getTotalHits().value;SearchHit[] hits = searchHits.getHits();// 遍历List hotels = new ArrayList<>();for (SearchHit hit : hits) {String json = hit.getSourceAsString();// 反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);hotels.add(hotelDoc);}// 封装返回return new PageResult(total,hotels);}
}

重新启动服务进行测试(过滤成功!!!
在这里插入图片描述

案例三: 我附近的酒店
前端页面点击定位后,会将你所在的位置发送到后台。我们要根据这个坐标,将酒店结果按照到这个点的距离升序排序。

在这里插入图片描述
1、修改RequestParams参数,接收location字段

// 位置private String location;

2、修改search方法业务逻辑,如果location有值,添加根据geo_distance排序的功能

//  2.3、 排序String location = params.getLocation();if (location!=null && !location.equals("")){request.source().sort(SortBuilders.geoDistanceSort("location",new GeoPoint(location))// 排序方式.order(SortOrder.ASC)// 指定单位.unit(DistanceUnit.KILOMETERS));}

按照距离排序后,还需要显示具体的距离值:
① HotelDoc实体类中添加distance属性
在这里插入图片描述

② 修改结果解析响应

private PageResult handleResponse(SearchResponse response) {// 4、解析响应SearchHits searchHits = response.getHits();long total = searchHits.getTotalHits().value;SearchHit[] hits = searchHits.getHits();// 遍历List hotels = new ArrayList<>();for (SearchHit hit : hits) {String json = hit.getSourceAsString();// 反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);// 获取排序值Object[] sortValues = hit.getSortValues();if (sortValues.length>0){Object value = sortValues[0];hotelDoc.setDistance(value);}hotels.add(hotelDoc);}// 封装返回return new PageResult(total,hotels);}
}

重新启动服务进行测试(成功显示数据且排序成功!!!
在这里插入图片描述

案例四:让指定的酒店在搜索结果中排名置顶
给需要置顶的酒店文档添加一个标记。然后利用function score给带有标记的文档增加权重。效果如下所示:
在这里插入图片描述

1、给HotelDoc类添加isAD字段,Boolean类型
在这里插入图片描述

2、挑选几个你喜欢的酒店,给它的文档数据添加isAD字段,值为true
在这里插入图片描述

3、修改search方法,添加function score功能,给isAD值为true的酒店增加权重

private void buildBasicQuery(RequestParams params, SearchRequest request) {// 1、构建BooleanQueryBoolQueryBuilder boolQuery = QueryBuilders.boolQuery();// 关键字搜索String key = params.getKey();if (key == null || "".equals(key)) {boolQuery.must(QueryBuilders.matchAllQuery());} else {boolQuery.must(QueryBuilders.matchQuery("name", key));}// 城市条件 (term属于过滤条件放在must中会影响得分进而影响查询性能)if(params.getCity()!=null && !params.getCity().equals("")){boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));}// 品牌条件if(params.getBrand()!=null && !params.getBrand().equals("")){boolQuery.filter(QueryBuilders.termQuery("brand", params.getBrand()));}// 星级条件if(params.getStarName()!=null && !params.getStarName().equals("")){boolQuery.filter(QueryBuilders.termQuery("starName", params.getStarName()));}// 价格if(params.getMinPrice()!=null && params.getMaxPrice()!=null){boolQuery.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));}// 2、算分控制FunctionScoreQueryBuilder functionScoreQuery = QueryBuilders.functionScoreQuery(// 原始查询,相关性算分的查询boolQuery,// function score的数组new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{// 其中一个 function score 元素new FunctionScoreQueryBuilder.FilterFunctionBuilder(// 过滤条件QueryBuilders.termQuery("isAD",true),// 算分函数(分值*10)ScoreFunctionBuilders.weightFactorFunction(10))});request.source().query(functionScoreQuery);
}

广告置顶成功
在这里插入图片描述

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...