本文共 3913 字,大约阅读时间需要 13 分钟。
本文将介绍如何基于 Elasticsearch 实现酒店搜索功能,包括搜索框、分页、过滤、定位以及广告优先排名等多个模块的开发与实现。
搜索框是用户与服务进行交互的主要入口。用户输入关键词后,系统需要将其转化为有效的搜索请求参数。
搜索请求的格式为标准的 Elasticsearch JSON 格式。用户输入关键词后,前端作为介质将请求转化为 JSON 格式后发送至后端。
后端接收 JSON 参数后,调用 Elasticsearch 进行搜索,返回数据总数及酒店数据列表。需注意响应格式需提前与前端约定。
分页功能的实现与搜索框无异。点击分页按钮后,会重复发送相同的搜索请求。分页参数需与前端同步更新。
@Datapublic class RequestParams { private String key; private Integer page; private Integer size; private String sortBy;}@Datapublic class PageResult { private Long total; private List hotels; public PageResult(Long total, List hotels) { this.total = total; this.hotels = hotels; }} @RestController@RequestMapping("/hotel")public class HotelController { @Autowired private IHotelService hotelService; @RequestMapping("/list") public PageResult search(@RequestBody RequestParams params) { return hotelService.search(params); }}public class HotelService extends ServiceImpl { @Autowired private RestHighLevelClient client; @Autowired private ObjectMapper objectMapper; public PageResult search(RequestParams params) throws IOException { try { SearchRequest request = new SearchRequest("hotel"); String searchContent = params.getKey(); if(!StringUtils.hasLength(searchContent)) { request.source().query(QueryBuilders.matchAllQuery()); } else { request.source().query(QueryBuilders.matchQuery("all", searchContent)); } Integer page = params.getPage(); Integer size = params.getSize(); if(page == null || size == null) { throw new IOException("分页数据不能为空!"); } request.source().from((page-1)*size).size(size); SearchResponse response = client.search(request, RequestOptions.DEFAULT); return handlerResponse(response); } catch (IOException e) { System.out.println("[HotelService] 搜索失败!"); e.printStackTrace(); return null; } } private PageResult handlerResponse(SearchResponse response) throws JsonProcessingException { SearchHits hits = response.getHits(); long total = hits.getTotalHits().value; SearchHit[] hits1 = hits.getHits(); List hotelDocList = new ArrayList<>(); for(SearchHit searchHit : hits1) { String json = searchHit.getSourceAsString(); HotelDoc hotelDoc = objectMapper.readValue(json, HotelDoc.class); Object[] sortValues = searchHit.getSortValues(); if(sortValues != null && sortValues.length > 0) { hotelDoc.setDistance(sortValues[0]); } hotelDocList.add(hotelDoc); } return new PageResult(total, hotelDocList); }} 为提高搜索效率,支持用户根据品牌、城市、星级等条件进行过滤。
@Datapublic class RequestParams { private String key; private Integer page; private Integer size; private String sortBy; private String brand; private String starName; private String city; private Integer minPrice; private Integer maxPrice;}使用 BoolQuery,结合 term 查询和 range 查询实现过滤功能。具体逻辑可封装至方法中。
推荐使用 boolQuery 和 functionScoreQuery 来处理高级查询和排序。
用户点击搜索后,将指定酒店置于搜索结果顶部。需张广告标记字段并在 Elasticsearch 中进行函数评分。
isAD 字段标识广告数据@Datapublic class HotelDoc { private Boolean isAD; // 其他字段尽量简化}使用 functionScoreQuery 对匹配到 isAD: true 的酒店赋予更高权重,提升搜索排名。
转载地址:http://weeyk.baihongyu.com/