【Elasticsearch】黑马旅游案例(三)

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 【Elasticsearch】黑马旅游案例(三)

4.3.5.排序距离显示

重启服务后,测试我的酒店功能:

发现确实可以实现对我附近酒店的排序,不过并没有看到酒店到底距离我多远,这该怎么办?

排序完成后,页面还要获取我附近每个酒店的具体距离值,这个值在响应结果中是独立的:

因此,我们在结果解析阶段,除了解析source部分以外,还要得到sort部分,也就是排序的距离,然后放到响应结果中。

我们要做两件事:

  • 修改HotelDoc,添加排序距离字段,用于页面显示
  • 修改HotelService类中的handleResponse方法,添加对sort值的获取

1)修改HotelDoc类,添加距离字段

package cn.itcast.hotel.pojo;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class HotelDoc {
    private Long id;
    private String name;
    private String address;
    private Integer price;
    private Integer score;
    private String brand;
    private String city;
    private String starName;
    private String business;
    private String location;
    private String pic;
    // 排序时的 距离值
    private Object distance;
    public HotelDoc(Hotel hotel) {
        this.id = hotel.getId();
        this.name = hotel.getName();
        this.address = hotel.getAddress();
        this.price = hotel.getPrice();
        this.score = hotel.getScore();
        this.brand = hotel.getBrand();
        this.city = hotel.getCity();
        this.starName = hotel.getStarName();
        this.business = hotel.getBusiness();
        this.location = hotel.getLatitude() + ", " + hotel.getLongitude();
        this.pic = hotel.getPic();
    }
}


2)修改HotelService中的handleResponse方法

重启后测试,发现页面能成功显示距离了:

4.4.酒店竞价排名

需求:让指定的酒店在搜索结果中排名置顶

4.4.1.需求分析

要让指定酒店在搜索结果中排名置顶,效果如图:

页面会给指定的酒店添加广告标记。

那怎样才能让指定的酒店排名置顶呢?

我们之前学习过的function_score查询可以影响算分,算分高了,自然排名也就高了。而function_score包含3个要素:

  • 过滤条件:哪些文档要加分
  • 算分函数:如何计算function score
  • 加权方式:function score 与 query score如何运算

这里的需求是:让指定酒店排名靠前。因此我们需要给这些酒店添加一个标记,这样在过滤条件中就可以根据这个标记来判断,是否要提高算分

比如,我们给酒店添加一个字段:isAD,Boolean类型:

  • true:是广告
  • false:不是广告

这样function_score包含3个要素就很好确定了:

  • 过滤条件:判断isAD 是否为true
  • 算分函数:我们可以用最简单暴力的weight,固定加权值
  • 加权方式:可以用默认的相乘,大大提高算分

因此,业务的实现步骤包括:

  1. 给HotelDoc类添加isAD字段,Boolean类型
  2. 挑选几个你喜欢的酒店,给它的文档数据添加isAD字段,值为true
  3. 修改search方法,添加function score功能,给isAD值为true的酒店增加权重

4.4.2.修改HotelDoc实体

cn.itcast.hotel.pojo包下的HotelDoc类添加isAD字段:

4.4.3.添加广告标记

接下来,我们挑几个酒店,添加isAD字段,设置为true:

POST /hotel/_update/1902197537
{
    "doc": {
        "isAD": true
    }
}
POST /hotel/_update/2056126831
{
    "doc": {
        "isAD": true
    }
}
POST /hotel/_update/1989806195
{
    "doc": {
        "isAD": true
    }
}
POST /hotel/_update/2056105938
{
    "doc": {
        "isAD": true
    }
}

4.4.4.添加算分函数查询

接下来我们就要修改查询条件了。之前是用的boolean 查询,现在要改成function_socre查询。

function_score查询结构如下:

对应的JavaAPI如下:

我们可以将之前写的boolean查询作为原始查询条件放到query中,接下来就是添加过滤条件算分函数加权模式了。所以原来的代码依然可以沿用。

修改cn.itcast.hotel.service.impl包下的HotelService类中的buildBasicQuery方法,添加算分函数查询:

private void buildBasicQuery(RequestParams params, SearchRequest request) {
    // 1.构建BooleanQuery
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    // 关键字搜索
    String key = params.getKey();
    if (key == null || "".equals(key)) {
        boolQuery.must(QueryBuilders.matchAllQuery());
    } else {
        boolQuery.must(QueryBuilders.matchQuery("all", key));
    }
    // 城市条件
    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),
                // 算分函数
                ScoreFunctionBuilders.weightFactorFunction(10)
            )
        });
    request.source().query(functionScoreQuery);
}
相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
8月前
|
存储 关系型数据库 数据库
ElasticSearch深度解析入门篇:高效搜索解决方案的介绍与实战案例讲解,带你避坑
ElasticSearch深度解析入门篇:高效搜索解决方案的介绍与实战案例讲解,带你避坑
ElasticSearch深度解析入门篇:高效搜索解决方案的介绍与实战案例讲解,带你避坑
|
8月前
|
存储 监控 安全
大厂案例 - 腾讯万亿级 Elasticsearch 架构实践1
大厂案例 - 腾讯万亿级 Elasticsearch 架构实践
114 0
|
1月前
|
自然语言处理 Java 索引
SpringBoot 实现 elasticsearch 查询操作(RestHighLevelClient 的案例实战)
SpringBoot 实现 elasticsearch 查询操作(RestHighLevelClient 的案例实战)
43 1
|
1月前
|
存储 Serverless 定位技术
深度探索 Elasticsearch 8.X:function_score 参数解读与实战案例分析
深度探索 Elasticsearch 8.X:function_score 参数解读与实战案例分析
17 0
|
1月前
|
JSON 前端开发 Java
【Elasticsearch】黑马旅游案例
【Elasticsearch】黑马旅游案例
183 0
|
8月前
|
存储 Java 数据库
大厂案例 - 腾讯万亿级 Elasticsearch 架构实践2
大厂案例 - 腾讯万亿级 Elasticsearch 架构实践2
44 0
|
11月前
|
自然语言处理 Java 索引
SpringBoot 实现 elasticsearch 查询操作(RestHighLevelClient 的案例实战)
上一节讲述了 SpringBoot 实现 elasticsearch 索引操作,这一章节讲述 SpringBoot 实现 elasticsearch 查询操作。 1. 环境准备 案例用到的索引库结构
|
11月前
|
前端开发 Java 定位技术
【Elasticsearch】黑马旅游案例(二)
【Elasticsearch】黑马旅游案例(二)
145 0
|
11月前
|
JSON 前端开发 Java
【Elasticsearch】黑马旅游案例(一)
【Elasticsearch】黑马旅游案例
178 0
|
1月前
|
Java Maven 开发工具
【ElasticSearch 】IK 分词器安装
【ElasticSearch 】IK 分词器安装
43 1