酒店数据全文检索练习(2)-按距离排序实现离我最近功能

前言

上一节(酒店数据全文检索练习(1)-关键词查询与结果条件过滤)我们讲了如何利用elasticsearch的关键词进行全文检索和数据过滤,这一节我们主要讲排序功能的实现

排序

地理位置排序

前端有一个功能,通过点击定位图标,会查询你当前的位置,并发送当前位置的请求到后台,我们可以根据这个实现我附近的酒店功能

image-20220121105904305

image-20220121110155958

这个字段是location,通过逗号分割的经纬度,我们在请求对象RequestParams中添加这个字段

/**
 * 当前定位
 */
private String location;

在前端中有一个distance字段,来获取按距离排序后的结果,我们把这个字段加到返回对象HotelDoc

image-20220121112559795

private Object distance;

然后我们修改HotelServicelist方法

@Override
public ResponseObject list(RequestParams requestParams) {
    SearchRequest request = new SearchRequest("hotel");

    //构建BooleanQuery
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

    //构建查询语句
    buildBasicQuery(requestParams, boolQuery);

    request.source().query(boolQuery);
    //分页
    int page = requestParams.getPage();
    int size = requestParams.getSize();
    request.source().from((page - 1) * size).size(size);

    // 排序
    String location = requestParams.getLocation();
    if (StringUtils.isNotEmpty(location)) {
        request.source().sort(SortBuilders
                              .geoDistanceSort("location", new GeoPoint(location))
                              .order(SortOrder.ASC)
                              .unit(DistanceUnit.KILOMETERS) //单位:km
                             );
    }

    ResponseObject responseObject = new ResponseObject();
    List<HotelDoc> hotelDocList = new ArrayList<>();
    try {
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        long total = hits.getTotalHits().value;
        responseObject.setTotal(total);
        SearchHit[] searchHits = hits.getHits();
        for (SearchHit searchHit : searchHits) {
            HotelDoc hotelDoc = JSONObject.parseObject(searchHit.getSourceAsString(), HotelDoc.class);
            //处理排序结果
            Object[] sortValues = searchHit.getSortValues();
            if (sortValues != null && sortValues.length != 0) {
                hotelDoc.setDistance(sortValues[0]);
            }
            hotelDocList.add(hotelDoc);
        }
        responseObject.setHotels(hotelDocList);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return responseObject;
}

重启项目,然后点击定位图标,可以看到如图标注的距离,但是由于数据中没有和我很近的数据,最近的都是深圳🤣

image-20220121113127583

评价与价格排序

页面上还有两个排序方式,评价,价格 其实和距离排序差不多,评价,价格排序是通过前端sortBy字段的值,后端判断用什么进行排序的

image-20220121115432905

那么代码如下:

@Override
public ResponseObject list(RequestParams requestParams) {
    SearchRequest request = new SearchRequest("hotel");

    //构建BooleanQuery
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

    //构建查询语句
    buildBasicQuery(requestParams, boolQuery);

    request.source().query(boolQuery);
    //分页
    int page = requestParams.getPage();
    int size = requestParams.getSize();
    request.source().from((page - 1) * size).size(size);

    // 排序
    String location = requestParams.getLocation();
    if (StringUtils.isNotEmpty(location)) {
        request.source().sort(SortBuilders
                .geoDistanceSort("location", new GeoPoint(location))
                .order(SortOrder.ASC)
                .unit(DistanceUnit.KILOMETERS) //单位:km
        );
    }

	// 价格和评价分数排序
    String sortBy = requestParams.getSortBy();
    if (StringUtils.isNotEmpty(sortBy)){
        if ("score".equals(sortBy)){
            request.source().sort("score",SortOrder.ASC);
        }else if ("price".equals(sortBy)){
            request.source().sort("price",SortOrder.ASC);
        }
    }

    ResponseObject responseObject = new ResponseObject();
    List<HotelDoc> hotelDocList = new ArrayList<>();
    try {
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        long total = hits.getTotalHits().value;
        responseObject.setTotal(total);
        SearchHit[] searchHits = hits.getHits();
        for (SearchHit searchHit : searchHits) {
            HotelDoc hotelDoc = JSONObject.parseObject(searchHit.getSourceAsString(), HotelDoc.class);
            //处理排序结果
            Object[] sortValues = searchHit.getSortValues();
            if (sortValues != null && sortValues.length != 0) {
                hotelDoc.setDistance(sortValues[0]);
            }
            hotelDocList.add(hotelDoc);
        }
        responseObject.setHotels(hotelDocList);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return responseObject;
}

看看效果

image-20220121120134999

大功告成,下一节(酒店数据全文检索练习(3)-定价排名广告置顶)我们讲竞价排名,将广告置顶。


酒店数据全文检索练习(2)-按距离排序实现离我最近功能
https://www.zhaojun.inkhttps://www.zhaojun.ink/archives/1011
作者
卑微幻想家
发布于
2022-01-21
许可协议