Spring Boot 整合 分布式搜索引擎 Elastic Search 实现 我附近的、酒店竞排

文章目录

  • ⛄引言
  • 一、我附近的酒店
    • ⛅需求分析
    • ⚡源码编写
  • 二、酒店竞价排名
    • ⌚需求分析
    • ⏰修改搜索业务
  • ✅效果图
  • ⛵小结

⛄引言

本文参考黑马 分布式Elastic search
Elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以帮助我们从海量数据中快速找到需要的内容

一、我附近的酒店

⛅需求分析

在酒店列表页的右侧,有一个小地图,点击地图的定位按钮,地图会找到你所在的位置:

在这里插入图片描述

点击定位后,会发送给服务端以下请求json

在这里插入图片描述

我们要做的事情就是基于这个location坐标,然后按照距离对周围酒店排序。实现思路如下:

  • 修改RequestParams参数,接收location字段
  • 修改search方法业务逻辑,如果location有值,添加根据geo_distance排序的功能

⚡源码编写

修改实体类

import lombok.Data;@Data
public class RequestParams {private String key;private Integer page;private Integer size;private String sortBy;private String city;private String brand;private String starName;private Integer minPrice;private Integer maxPrice;// 我当前的地理坐标private String location;
}

距离排序

我们以前学习过排序功能,包括两种:

  • 普通字段排序
  • 地理坐标排序

地理坐标 DSL 语法如下

GET /indexName/_search
{"query": {"match_all": {}},"sort": [{"price": "asc"  },{"_geo_distance" : {"FIELD" : "纬度,经度","order" : "asc","unit" : "km"}}]
}

添加距离排序

@Override
public PageResult search(RequestParams params) {try {// 1.准备RequestSearchRequest request = new SearchRequest("hotel");// 2.准备DSL// 2.1.querybuildBasicQuery(params, request);// 2.2.分页int page = params.getPage();int size = params.getSize();request.source().from((page - 1) * size).size(size);// 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));}// 3.发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 4.解析响应return handleResponse(response);} catch (IOException e) {throw new RuntimeException(e);}
}

排序距离展示

重启进行测试:

在这里插入图片描述

的却可以实现 我附近的酒店距离排序,但是没有展示距离我们有多远,这个我们应该怎么实现呢?

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

在这里插入图片描述

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

我们要做两件事:

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

添加距离排序字段

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();}
}

修改 handleResponse 方法

在这里插入图片描述

重启进行测试

在这里插入图片描述

已成功展示距离。

二、酒店竞价排名

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

⌚需求分析

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

在这里插入图片描述

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

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

我们之前学习过的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的酒店增加权重

⏰修改搜索业务

添加广告标记

修改实体类

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;// 加入广告标识private Boolean isAD;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();}
}

随便设置几个作为广告置项

POST /hotel/_update/2056105938
{"doc": {"isAD": true}
}POST /hotel/_update/38609
{"doc": {"isAD": true}
}

添加算分函数查询

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

function_score查询结构如下:

在这里插入图片描述

对应的JavaAPI如下:

在这里插入图片描述

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

加入算分查询

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("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);
}

效果展示

在这里插入图片描述

✅效果图

在这里插入图片描述

⛵小结

以上就是【Bug 终结者】对 Spring Boot 整合 分布式搜索引擎 Elastic Search 实现 搜索、分页与结果过滤 的简单介绍,ES搜索引擎无疑是最优秀的分布式搜索引擎,使用它,可大大提高项目的灵活、高效性! 技术改变世界!!!

如果这篇【文章】有帮助到你,希望可以给【Bug 终结者】点个赞👍,创作不易,如果有对【后端技术】、【前端领域】感兴趣的小可爱,也欢迎关注❤️❤️❤️ 【Bug 终结者】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💝💝💝!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/7334.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

账号安全总结-业务安全测试实操(27)

电子邮件账号泄露事件 电子邮箱业务基于计算机和通信网的信息传递业务,利用电信号传递和存储信息,为用户传送电子信函、文件数字传真、图像和数字化语音等各类型的信息。电子邮件最大的特点是,人们可以在任何地方、任何时间收、发信件,解决了时空的限制,大大提高了工作效…

【Java用法】Java在Linux下获取当前程序路径以及在Windows下获取当前路径对比

Java在Linux下获取当前程序路径以及在Windows下获取当前路径对比 log.info("分隔符:File.separator[{}]", File.separator); log.info("用户主目录:user.home[{}]", System.getProperties().getProperty("user.home")); l…

MySQL中常用查看锁和事务的SQL语句

MySQL中常用查看锁和事务的SQL语句 当我们在使用MySQL数据库时,了解如何查看锁和事务的状态是非常重要的。这些信息可以帮助我们调试和优化数据库性能,以及解决并发访问的问题。在本博客中,我将介绍一些常用的MySQL查询语句,用于查…

JMeter之IP欺骗技术(模拟不同的IP地址并发请求)

目录 前言: 第一步:在负载机上绑定IP地址 第二步:点击高级,添加伪造的IP地址 第三步:新增IP地址复制到文本 第四步:新建参数化请求 第五步:新建压力测试脚本 第六步:配置线程…

Spring Boot日志文件

目录 前言🍭 一、日志的作用🍭 1、日志真实使用案例:🍉 二、日志怎么用🍭 1、自定义日志打印🍉 Ⅰ、在程序中得到日志对象🍓 常见的日志框架说明(了解)&#x1f35…

GAD7980/CL1680/AD7980详解与开发说明

目录 1 概述2 GAD7980简介3 用法时序4 参数计算与参数解释4.1 采样率4.2 转换时间4.3 采集时间5 采样数值折算6 设计注意事项7 代码demo 1 概述 本文用于讲述GAD7980的功能与用法,以及其中一些参数的计算方法,用法时序,输出数值等等&#xf…

Django学习笔记-VS Code本地运行项目

截止到上一章节:Django 学习笔记-Web 端授权 AcWing 一键登录,我们的项目一直是部署在云服务器上,包括编写代码以及调试运行也是在云服务器上,现在我们尝试将其放回本地运行。 CONTENTS 1. 将项目传到本地2. 虚拟环境配置3. 修改项…

postgresql 获取建表信息

通过函数获取 创建自定义函数 CREATE OR REPLACE FUNCTION tabledef(text,text) RETURNS text LANGUAGE sql STRICT AS $$ WITH attrdef AS (SELECT n.nspname, c.relname, c.oid, pg_catalog.array_to_string(c.reloptions || array(select toast. || x from pg_catalog.un…

照片jpg大小kb如何修改?图片在线压缩大小怎么处理?

最近需要在各种报名平台上传照片的小伙伴比较多,难免会遇到需要压缩jpg图片的情况,那么怎么才能将jpg图片压缩(https://www.yasuotu.com/jpg)呢?今天介绍一个图片在线压缩大小的方法,不用下载任何软件就可以…

数据结构--双端队列

数据结构–双端队列 双端队列(Double-ended Queue,简称Deque)是一种具有队列和栈特性的数据结构,可以在队列的两端进行插入和删除操作。双端队列允许从前端和后端同时进行插入和删除操作,因此可以称为“两端都可以进出…

大势速影:机载激光快速建模测绘装备

实景三维模型高逼真、高真实、高精度的展示地物的几何结构、纹理色彩、空间位置等信息,在当前测绘应急保障、规划等领域具备极大的应用价值。但是,激光雷达和倾斜摄影建模技术均无法较好的满足快速建模应用需求,具体表现在:激光点…

rsync远程同步(可爱可抵漫长岁月)

文章目录 一、简介二、部署rsync主客服务器1.关闭防火墙(真的老生常谈了 一生之敌!)2.建立/etc/rsyncd.conf 配置文件3.客户端配置4.发起端配置 rsyncinotify 三、拓展使用rsync来实现快速删除大量文件。 一、简介 什么是rsync? …