京东外卖,探索「距离最近」排序背后的秘密

@Autowired(required=false)注入注意的问题 1、前言在使用spring开发过程中,我们基本上都是使用@Autowired这个注解,用来注入已有的bean。但是有些时候,会注入失败。当我们加上参数(required=false)就能解决。今天整理一个我在实际开发中的例子2、required属性@Autowired(required=true):当使用@Autowired注解的时候,其实默认就是@Autowired(required=true)... 阅读详情

平台奖励创作,可能会升级VIP文章,可以移步我的公众号:【编程朝花夕拾】,且可获取首发内容。

在这里插入图片描述

1、引言

京东外卖于‌2025年2月11日正式开放,标志着京东正式进军外卖行业。浏览页面时,在筛选项里面看到了「距离最近」的筛选项,点了一下就按照商户和当前位置正序排列了。

这个功能其实其他外卖类、旅游类、地图类的APP中经常看到。今天我们一起聊一下背后的技术方案。

2、背后的技术

地理位置(Geolocation)距离的不再是简单的距离比较,而是实时的经纬度的计算。因为你在不同的地方,商家离你的位置都是变化的。

Geolocation的简称是GEO。地球经纬度,将地球看做一个球体。将A、B两点的作为一个剖面,就会得到一个圆形,A、B两点的之间的距离不再试一条直线,而是一条弧线。两点的距离就是这个弧长。

常用的计算方式,离不开数学的三角函数:

  • 球面余弦定理:适用于远距离计算,但近距离可能有舍入误差
  • Vincenty公式:基于椭球模型,精度更高但计算复杂
  • Haversine公式:平衡精度与复杂度的最佳选择,适用于导航、地图服务等常见场景

了解一下晦涩难懂的Haversine公式:

看着复杂,其实按照参数代入即可。当然这个不是今天的目的。

Java作为一门面向对象的语言,可以不用关注具体的实现,只要有现成的工具,调用即可。

3、问题难点

了解了经纬度的计算,无论是我们自己编码、套用公式还是使用一些在线工具根据两点计算出距离,这些都不能满足类似「京东外卖」这样的排序。

因为排序功能是针对全量的数据。如果单纯的计算出距离,不说海量万级数据都有可能将内存榨干,更不用说影响用户体验了。

难点来了:如何通过经纬度实时计算给万级数据排序呢?

4、Mysql 5.7.6+

Mysql 是大部分程序员都会接触的数据库,用来存储数据。Mysql从 5.7.6 版本 开始正式支持基于地理坐标系(如WGS84)的经纬度计算功能,关键改进是引入了 ST_Distance_Sphere 函数,用于计算球面距离(即地球表面的实际距离)。

数据准备:

上海(POINT(121.4737, 31.2304))、北京(POINT(116.4074, 39.9042))

SELECT ST_Distance_Sphere(
    POINT(116.4074, 39.9042),  -- 北京
    POINT(121.4737, 31.2304)    -- 上海
) AS distance_meters;
-- 结果约为 1,066,000 米(约1066公里)

距离正序排列的使用:

-- 单位米
SELECT
    id,
    latitude,
    longitude,
    ST_DISTANCE_SPHERE(
        POINT(target_longitude, target_latitude),
        POINT(longitude, latitude)
    ) AS distance
FROM table_name 
ORDER BY distance ASC;

5、Redis GEO

Redis中的GEO数据类型是Redis3.2.0开始有的。

实战用到的函数:GEORADIUS

# 根据当前经纬度获取方圆范围内的成员
GEORADIUS key longitude latitude radius M | KM | FT | MI [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC | DESC] [STORE key | STOREDIST key]

参数含义:

  • WITHCOORD 获取经纬度
  • WITHDIST 获取距离
  • WITHHASH 获取成员Hash
  • COUNT 限制罗列的成员数量
  • ASE | DESC 排序
  • STORE key 将返回的地理位置信息保存到一个key里面
  • STOREDIST key 将返回的目标距离保存到一个key里面

实战:

假设当前的地点位置:上海(POINT(121.4737, 31.2304)

# 查询cities这个key中距离上海(POINT(121.4737, 31.2304) 50公里以内的元素,并正序排列
GEORADIUS cities 121.4737 31.2304 50 KM WITHDIST ASC

像了解关于Redis GEO更多知识可以查看以往文章:

https://mp.weixin.qq.com/s/MbQXBvN2kPUc3T5W21Bbuw

6、小结

上面介绍两种最常用且简单的方法,你还知道其他方法么?评论区留言讨论。

方法再多,只不过使我们使用的工具或者手段。日常中你可能平时常见的一个小功能,背后可能都有极其复杂的技术支撑。比如我们进场使用的地图,已经接入北斗导航,背后的技术更是不言而喻。

Spring Boot配合Postgresql和MybatisPlus实现外卖平台常见的距离你xxx米功能 最近在做一个业务功能,需求涉及到了通过终端的定位获取距离终端最近的实体店铺的需求。因为之前没有涉及到地理位置坐标计算距离的知识,只知道redis可以计算两个坐标点(经纬度)之间的距离。但是不满足目前的需求,因为除了计算距离外还要进行筛选、排序、分页。所以就不考虑在redis实现。更不可能全表查询内存排序。所以上网搜索资料,找到了pgsql的插件postgis,是数据库层面支持经纬度距离计算的插件。postgis官网:https://postgis.net//*** 描述:* 阅读详情

相关推荐

10个你每天都在用却浑然不觉的AI日常场景

人工智能早已超越概念阶段,成为嵌入日常生活的底层能力。其核心原理在于轻量模型在端侧完成实时推理,依托行为预测、联邦学习与多模态感知实现无感交互。技术价值不在于炫技,而在于降低使用门槛、提升决策效率、延长设备自主性——比如自动归类照片、预填外卖备注、精准唤醒单个灯具。这些能力广泛应用于智能终端、生活服务、健康健身、家庭IoT等高频场景,背后是模型蒸馏、量化剪枝、情境感知等关键技术的成熟落地。本文聚焦真实可感的10个案例,揭示AI如何以‘毛细血管级’方式渗透衣食住行。

weixin_33769125的博客 462

用ES实现根据经纬度由近及远推荐店铺

用ElasticSearch实现根据经纬度由近及远推荐店铺

abc_hom的博客 1967

jsp页面打jar包及其引用

1、前言 项目开发中,需要把一些公共页面抽取到公用的项目中,打成jar包全局使用,便于修改和维护。最常见的就是会把公用的方法或者实体类打成jar包,这种很好用,直接导入依赖,导包就完事了。但是页面的打包笔者开发的时候,搞了好久,终于搞定。记录一下,方便日后使用。 2、页面的打包 正确的打包方式,开发者可以像页面在项目中一样的方式去引用(js、css等同理)。 jar工程只用两个主要的文件夹src

static_coder的博客 1万+

logback的简单使用

1、前言 查了很多资料,都说logback的性能都要比log4j的性能要好,logback逐渐要取代log4j。今天对logback作一个简单的整理。 2、logback的依赖坐标 <!-- <dependency> <groupId>org.slf4j</groupId> <artifactId&...

static_coder的博客 2万+

Redis7系列:Redis对决RedisStack

Redis 是一个开源的内存数据库,以高性能、低延迟著称,支持基础数据结构(如字符串、哈希、列表、集合、有序集合等),常用于缓存、消息队列、实时数据处理等场景。Redis Stack 是 Redis 的扩展版本,整合了 Redis 核心数据库与多个高级功能模块(如全文搜索、JSON 文档存储、图数据库、时间序列等),提供“一站式”解决方案,简化了复杂数据场景的开发。

static_coder的博客 2907

【管理科学】第六十三篇 企业管理者招聘与人才博弈战略02

编号类型领域问题问题的数学分析(含逐步推理与数值范围)方法/手段/步骤/流程/话术/策略/行为/时序的所有内容和步骤(含数学表达式与数值分析)时序数学表达式及周期行动的数学表达式(含数值范围)关联知识和法律法规651组织博弈成本控制如何在保证质量的前提下有效控制成本?逐步推理: 1. 成本控制模型:成本每降低10%,利润可提升15%~25%。但过度降本可能影响质量和员工士气。 2. 控制效果:有效的成本控制可使利润率提升5%~10%。 3. 法律风险:需遵守劳动法和产品质量法。步骤与数学表

weixin_49199313的博客 489

FORM表单的几大属性

FORM表单的几大属性问题引入 在做一个活动支付项目的时候,提交订单(form表单)跳转支付页面发现没有反应。经过断点排查发现断点也进了,不报错。但是返回的就是空白页,让人很纠结。 进过反复测试,才发现是杀毒软件拦截了form表单的请求。如何来解决这个问题呢?下来我们来看看Form表单的属性就会明白了。 FORM的属性 method属性:规定用于发送 form-data 的 HTTP

static_coder的博客 1万+

52页PPT智慧矿山数字化工业大数据平台建设方案

致力于为煤炭企业构建“全”、“统”、“通”、”智”的(大数据平台/数据中台)体系,基于“数字新基建”时代的数据价值思考,构建全域数字化矿区共享能力中心,助力煤炭企业实现数字化转型,打通底层系统之间数据壁垒,加强公司整体管理和安全生产系数,为运营提供数据统筹模型,实现重点数据实时监控和数据共享开放服务。综上所述,智慧矿山数据治理是一个系统性的工程,需要煤炭企业内各部门连同行业和政府监管部门通力协作,制定数据标准和管理规范,重塑煤炭企业数据架构和数据传输链路,打通智慧矿山数据壁垒,保障数据质量和数据安全。

zuoan1993的博客 1055

spring容器启动,初始化某个方法(init)

1、前言 很多时候,我们需要在项目启动的时候,就要完成某些方法的执行。今天整理了一个简单的方法,使用spring容器中bean的属性:init-method 2、代码/* 初始化的类。这里不需要添加任何注解 */ public class InitData { @Autowired private UserService userService; /*

static_coder的博客 1万+

手把手教你用Kokoro-82M-v1.1-zh搭建本地TTS服务(含WebSocket接口)

本文详细介绍了如何使用Kokoro-82M-v1.1-zh模型搭建本地TTS服务,包括环境配置、模型部署、WebSocket接口实现及性能优化。通过实战指南,开发者可以快速掌握本地部署TTS系统的关键技术,提升语音交互应用的开发效率。

weixin_30776273的博客 184

ESP32—C3实现网页跳转

用户点击HTML页面中的按钮。浏览器根据按钮的href属性向服务器发送HTTP GET请求。服务器根据请求的URL调用相应的回调函数。服务器发送包含新页面HTML内容的HTTP响应。浏览器解析并显示新的HTML页面。这个过程对于用户来说是无缝的,看起来就像是直接从一个页面跳转到另一个页面。实际上,背后发生了HTTP请求和响应的过程。

qq_59527512的博客 1024

图片转化为base64及上传

1、前言 很多时候我们需要将图片转化成base64,并且上传。这里整理了一些关于图片转化base64的方法,方便以后使用。 2、页面demo html> head lang="en"> meta charset="UTF-8"> title>图片转化成Base64title> head>

static_coder的博客 1万+

3D Gaussian Splatting:用于实时的辐射场渲染

3D Gaussian Splatting:用于实时的辐射场渲染 3d gaussian splatting for real-time radiance field rendering

m0_51976564的博客 1万+

IntelliJ IDEA AI Assistant 携带OpenCode保姆级安装教程来了

的安装包,只不过界面没有明确的提示。可能由于网络原因下载失败,导致对话框无法使用。官方推出的 AI 驱动插件,专为软件开发设计。但是之前由于需要订阅才能使用,安装了之后又卸载了。安装上一节已经介绍了,这里不在赘述。明显显示已经安安装好了,几乎秒级安装,怎么感觉都有点离谱。但是在对话框无法使用,无法发出信息,也没有选择模型的地方。高版本中,必须登录之后才能使用,如果初次使用需要认证输入。其他的AI客户端大同小异,感兴趣的老铁快去试试吧。上面介绍了在线安装的方法。模式分析,没有问题了在修改。

static_coder的博客 8380

基于 SoC 的卷积神经网络车牌识别系统设计(1)引言

通过 CPU 软核 IP 在纯 FPGA 平台上构建一个 AI SoC 卷积神经网络车牌识别系统,其中,缩放、填充层、卷积层、ReLU、池化层、全连接层 IP 都是 Verilog 设计的,同时集成了各种高性能的 IP。这是最具挑战性的 AI SoC 芯片设计项目,集成了 Python 卷积神经网络代码、Verilog 卷积神经网络硬件设计、ARM SoC 设计、ARM 与 FPGA 的交叉编译流程等等。这不仅是科研学习、集创竞赛、秋招求职的一个极具优势的精彩项目,也是目前最火热的芯片行业之中的一个...

新芯设计的博客 3785

位置点位到达判断FC(Easy+Codesys+博途平台)

IN rActPositon REAL 轴当前实际位置 1IN arAbsPosition REAL[10] 各工作点位坐标 2IN rDeadZone REAL 位置达到判断域值 范围 3OUT abInAbsPos BOOL[10] 到达各绝对定位点位标志 位置到达输出 4VAR i INT 循环计数 5VAR rErr REAL 位置偏差 6。

RXXW_Dor的博客 537

IdentityHashMap :key值可以重复的Map集合

问题引入 初学java的时候,Map集合给人留下的印象就是键值对{key=value}的存储方式。并且我们知道键值对的可以唯一。但是Map容器真的不能存储key值相同的数据吗?查询API才发现有这么一个实现类可以存储重复的key:IdentityHashMap。IdentityHashMap简介 IdentityHashMap类同样实现了Map接口,拥有Map集合的一切特性。key值同样需要

static_coder的博客 5068

YOLOv11 改进入门篇 | 轻量级涨点技巧:GhostConv 替代普通卷积的实战指南

摘要: 本文介绍如何通过GhostConv改进YOLOv11,实现轻量化涨点。YOLOv11深度增加导致参数量、延迟和内存占用上升,GhostConv通过“本征特征+线性变换”策略,在精度几乎无损的情况下降低30%-50%计算量。文章详细解析GhostConv原理,对比普通卷积的参数量和FLOPs优势,并提供完整的代码级改造流程,包括模块实现、注册及网络配置。实验表明,该方法有效提升边缘端推理效率,适用于移动端等资源受限场景。

shrgegrb的博客 1657

TeamViewer、向日葵平替?这几款免费远程控制软件,真香!

号称时尚最安全的远程桌面。这是一款近年来在中国市场非常火爆的远程控制软件,因其对国内网络环境做了深度优化,在速度和延迟方面表现优异,被许多人视为。

static_coder的博客 4117

SolidWorks_模具设计5_分型线生成

分型线是模具设计的核心要素,直接影响产品质量、脱模可行性和制造成本。本文系统介绍了分型线生成技术,包括三种核心算法:基于凸包的方法适用于简单几何,可见性分析处理复杂曲面,曲率特征优化则能找到自然分界。文章提供了完整的Python实现示例,涵盖点云投影、网格处理和分型线评估等关键技术。通过理解这些原理和方法,工程师可以更高效地设计出满足外观要求、易于加工的分型线方案,显著提升模具设计质量和效率。

H17853509096的博客 180

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

针对iphone手机拍照片旋转90度问题解决

/* 1、图片上传的方法 */ @RequestMapping(value = "/uploadPic", method = RequestMethod.POST) @ResponseBody public JsonResult upload(@RequestParam("file") MultipartFile[] files){ Boolean flag

static_coder的博客 3939

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

springboot集成webSocket实现网络实时通讯

1、前言 在很多业务场景中,对实时数据要求比较高,我们就不能采用轮训拉取的方式来获取数据了。就可以采用websocket的长链接的形式,实时有服务端或者客户端推送数据,已达到数据的实时展示。 2、websocket简介 SpringBoot官方推荐的基于STOMP实现,STOMP:即Simple Text Orientated Messaging Protocol,它是一个简单的文本消息传输协议,属于 WebSocket 的子协议, 提供了一个可互操作的连接格式,允许STOMP客户端与任意...

static_coder的博客 3803

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

使用shiro标签遇到的坑

1、前言 使用shiro框架做权限控制是不错的选择,在使用shiro标签的过程中,是否会遇到一些坑呢。恰好笔者遇到了,在此记录一下。 2、shiro标签坑的描述 标签: <shiro:haspermission name="你的权限"></shiro:haspermission> 当使用的标签具有层级关系的时候,就有可能掉坑里,并且出不来。 例如: 第一层级...

static_coder的博客 3526

java使用Qrcode生成二维码(内嵌logo)

1、前言 整理一个使用qrcode.jar生成二维码的测试方法,以备后面学习使用。 2、使用准备Qrcode.jar3、demo /* 生成二维码 */ @RequestMapping(value="/creatQrcode", method = RequestMethod.POST) @ResponseBody public Object

static_coder的博客 3522

springmvc 框架中的数据的绑定:@InitBinder&@DateTimeFormat()

1、前言 表现层经常会接受页面表单的数据,springmvc框架提供了封装javaBean的功能,但是针对一些特殊的属性,则不会自动封装(比如java.util.Date类型),需要我们自行绑定。这里介绍两种解决的办法:@InitBinder&amp;@DateTimeFormat() 2、@DateTimeFormat()绑定Date类型 @DateTimeFormat()实现数据的绑定比...

static_coder的博客 3030
上一篇: 邮件通知,引发的线上的S级故障
下一篇: 短信被截断?5分钟用Java打造企业级短链服务
智_永无止境
博客等级 码龄10年 803粉丝 406原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智_永无止境

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值