当前位置:首页 > 行业知识 > 综合

搜索附近的人代码

关注:13 发布时间:2021-11-12 09:13:04

老板突然想上网找一个离方圆一公里的商业代理。明天上线!接到这个要求的时候差点吐血,时间太紧了。赶紧查查相关技术选型。经过很多麻烦,终于在晚上10点满足了这个需求,现在总结一下实现的大致思路。

2.mysql不适合

在满足需求的时候,首先要考虑现有的东西能不能满足,代价是什么。

我首先想到的是mysql。毕竟,大部分数据应该坚持到mysql.然而,使用mysql需要geohash.的自我计算。需要使用大量的数学和几何计算,并需要学习地理相关知识。门槛高,短时间内不可能完成要求。从长远来看,这不是mysql擅长的领域,因此不予考虑。

geohash可以参考其他文献

2.redis中的地球同步轨道

redis是比较熟悉的k-v数据库,它经常被用作高性能缓存数据库,并将在大多数项目中使用。自3.2版本以来,它提供了geo能力,用于实现附近位置、距离计算等依赖于地理位置信息的功能。geo"s的相关命令如下:

redis命令描述geohash返回一个或多个位置元素的geohash,这意味着geopos从key返回所有给定位置元素的位置(经度和纬度)。geodist返回两个给定位置之间的距离。地球位于给定的纬度和经度的中心。找出一定半径内的元素geoadd将指定的地理空间位置(纬度、经度、名称)添加到指定的关键georadiusbymember找出指定范围内的元素,中心点由给定的位置元素确定

redis会假设地球是一个完美的球体,所以可能会有一些位置计算偏差,据说是=0.5%。对于地理位置要求严格的需求,要进行一些场景测试,测试是否能满足需求。

2.1写地理信息

那么如何实现目标单位半径内的所有元素呢?我们可以将所有位置的经纬度转换成52位的geohash,通过上表中的geoadd写入redis。

命令格式:

geoadd关键经度纬度成员[经度纬度成员…]

相应的例子:

redis geo add cities : locs 117.12 39.08天津114.29 38.02石家庄

(整数)2

意思是在key.个城市的sorted set集合中添加经度为117.12、纬度为39.08的天津和经度为114.29、纬度为38.02的石家庄,您可以添加一个或多个位置。然后我们可以使用其他命令来计算地理位置。

有效经度范围从-180度到180度。有效纬度范围从-85.05112878度到85.0512778度。当坐标位置超过上述指定范围时,该命令将返回一个错误。

2.2统计单位半径内的面积

借助georadius,我们可以找到给定经纬度的某个半径内的所有元素。

命令格式:

地理坐标长纬度半径m | km | ft | mi[withourd][withdist][with ash][count][asc | desc]

这个命令比geoadd更复杂:

radius半径长度,必需。以下m、km、ft和mi是长度单位选项,四选一。

withcoord返回位置元素的经度和维度,这是可选的。

withdist返回位置元素和中心点以及位置元素之间的距离。距离的单位与查询单位相同,这不是必需的。

withhash以52位精度返回位置的geohash值,这是可选的。反正我很少用这个。也许其他一些偏向底层的lbs应用服务需要这个。

count返回合格位置元素的数量,这不是必需的。比如返回前10名,这样可以避免过多的一致结果带来的性能问题。

asc|desc排序方式,非必选。默认情况下返回未排序,但是大多数我们需要进行排序。参照中心位置,从近到远使用asc,从远到近使用desc。

例如,我们在城市:locs中查找以(115.03,38.44)为中心,方圆200公里的城市,结果包含城市名称、对应的坐标和距离中心点的距离(公里),并按照从近到远排列。命令如下:

redis georadius city : locas 115.03 38.44 200km,带coord witist asc

1) 1)石家庄

2) "79.7653"

3) 1) "114.29000169038772583"

2) "38.01999994251037407"

2) 1)"天津"

2) "186.6937"

3) 1) "117.02000230550765991"

2) "39.0800000535766543"

你可以加上计数一来查找比较近的一个位置。

3.基于redis geo实战

大致的原理思路说完了,接下来就是实操了。结合spring boot应用我们应该如何做?

3.1 开发环境

需要具有geo特性的redis版本,这里我使用的是redis 4。另外我们客户端使用spring-boot-starter-data-redis。这里我们会使用到使用对象。

3.2 批量添加位置信息

第一步,我们需要将位置数据初始化到redis中。在spring data redis中一个位置坐标(液化天然气,lat)可以封装到org。spring框架。数据。geo。要点对象中。然后指定一个名称,就组成了一个位置geo信息redistemplate。提供了批量添加位置信息的方法。我们可以将章节2.1中的添加命令转换为下面的代码:

mapstring,point points=new hashmap;

points.put("天津",new point(117.12,39.08));

points.put("石家庄",新点(114.29,38.02));

//redistemplate批量添加长狭潮道

redis模板。边界城市:个位置.添加(分);

可以结合弹簧靴提供的applicationrunner接口来实现初始化,建议从mysql等数据库同步地理信息。

@豆

public applicationrunner cache activeapprunner(redistemplate string,string redistemplate) {

返回参数- {

比较终字符串geo _ key=" cities:locs

//清理缓存

redistemplate。删除(geo _ key);

//建议从关系型数据库同步地理信息

mapstring,point points=new hashmap;

points.put("天津",new point(117.12,39.08));

points.put("石家庄",新点(114.29,38.02));

//redistemplate批量添加地理定位

boundgeooperationsstring,string geoops=redistemplate。boundgeoops(geo _ key);

geoops.add(点);

};

}

3.3 查询附近的特定位置

使用针对georadius命令也有封装:

地理位置半径(k键,内圆,地理坐标标准参数)

圆对象是封装覆盖的面积(图1),需要的要素为中心点坐标要点对象、半径(半径)、计量单位(公制),例如:

点点=新点(115.03,38.44);

公制公制=redisgeocommands .距离单位。kumts

距离距离=新距离(200,公制);

圆圆=新圆(点,距离);

地理标准用来封装georadius的一些可选命令参数,参见章节2.2中的带门、计数、asc等,例如我们需要在返回结果中包含坐标、中心距离、由近到远排序的前5条数据:

redisgeocommands .地理社区标准参数=地理社区。地理标准。newgeoradiusargs。includedistance。包括坐标。排序排序。极限(限制);

然后执行半径方法就会拿到georesultsredisgeocommands .地理位置字符串封装的结果,我们对这个可迭代对象进行解析就可以拿到我们想要的数据:

georesultsredisgeocommands .geolocationstring radius=redis template。opsforgeo。半径(geo_stage,圆,args);

if (radius!=) {

list staged to staged tos=new arraylist;

半径。foreach(地理定位地理结果-->

重新调用命令地理位置字符串内容=地理位置

georesult . getcontent;

//成员姓名如天津

string name=content . getname;

//对应的经纬度坐标

point pos=content . getpoint;

//到中心点的距离

distance dis=geolocationgeoresult . getdistance;

});

}

3.4删除元素

有时我们可能需要删除位置元素,但是redis的geo没有删除成员的命令。但是因为它的底层是zset,我们可以借助zrem命令删除,对应的java代码是:

redistemplate . boundsetops(geo _ stage)。移除(“天津”);

4.摘要

,我们使用redis"sgeo功能来实现附近常见的地理信息查询需求,简单易用。事实上,nosql,的另一个mongodb数据库,也可以使用。在数据量较小的情况下,redis能够很好地满足需求。如果数据量大,可以用mongodb.来实现,本文涉及的demo可以通过文末相关文章的链接来获得。

猜你喜欢

  • 日本当年为什么攻打珍珠港?

    日本当年为什么攻打珍珠港?80人支持

    二战初期,美国远离主战场,所以大陆没有受到战争的影响,美国人民过着相对稳定的生活。然而,日本毫无征兆地轰炸了美国的珍珠港,使美国卷入了一场残酷的战争。日本为什么要这么做?主…

  • 支付宝可以薅的羊毛

    支付宝可以薅的羊毛23人支持

    这篇文章是一个失败的薅羊毛战略,但我不想让我努力工作的战略付诸东流。发出去!如果能帮助无意看这篇文章的人避坑呢?支付宝-财富有相关活动吗?像前几天一样,画了15.18元。(是超…

  • 拼多多出事改简介?

    拼多多出事改简介?58人支持

    近日,拼多多一名员工因过度劳累死亡,在网上引起轩然大波。消息称,死亡女孩已火化,相关后续治疗仍在进一步协调中。事件发生后,平台在某平台上进行了动态开发。动态内容一般表示现…

  • 为什么不建议年轻人一直刷抖音?

    为什么不建议年轻人一直刷抖音?45人支持

    作为目前短视频的主流平台,tik tok每天有6亿用户,可以说是全民的tik tok。从70、80年代到三、四岁的孩子,tik tok是惯的。虽然是社会的发展,科技的进步,但我个人觉得这不是一…

  • 直接让微信语音变声的

    直接让微信语音变声的25人支持

    众所周知,qq有自己的语音变声,不需要编辑就可以发送。都是老马产品,微信没有这么好玩的功能。我也表示无奈。然而今天,陶涛给了每个人分享一个手机聊天变声的技巧,和叔叔可以在…

  • 函授和网络教育有什么区别

    函授和网络教育有什么区别93人支持

    如果我们一直在大专或更低的教育水平,我们会不断失去更多的信心,然后在职业发展的过程中不断抑郁。为了使我们能够更快地进入社会并找到一份稳定的工作,教育是必不可少的。对于…

  • 互联网上神秘的一群人:羊毛党

    互联网上神秘的一群人:羊毛党13人支持

    大家好,我是网购的先锋。今天,我们来谈谈“羊毛党”。相信大家都听说过羊毛党这个词,但是不清楚他们在做什么。大环境的形成据统计,现在的网购会员大约有6.39亿。由于互联网的快…

  • 抖音注销后是什么状态

    抖音注销后是什么状态116人支持

    今天是全新的一天,11月的第一天,还有61天进入2021年。今天的自己很不一样,没有过去的颓废,心里有一丝期待。今天,tik tok的帐户被取消,同时卸载。我从17年开始接触tik tok,3年多…

  • 股票停牌是好是坏

    股票停牌是好是坏51人支持

    停牌通常是由于一些市场消息或上市公司想发布的最大事件。为了维护投资市场的公平正义原则,证券交易所采取了突然停牌的方式。大多数情况下,上市公司停牌是在收盘后的晚上宣布…

  • 浪花黑卡怎么使用?

    浪花黑卡怎么使用?37人支持

    微信和支付宝可以说是两个“国货软件”,在中国大约有11亿用户。支付宝先后推出了花店和贷店,受到大家的欢迎。对于很多微信用户来说,他们希望微信也能推出类似支付宝的花店、借…

  • 无理数包括哪些

    无理数包括哪些34人支持

    什么是无理数?很多学生在接触无理数时不知所措,有时会让人感到头疼。今天极客数学团队整理了关于无理数的知识点和相关练习。我们来看看什么是无理数。1.什么是无理数?无理数是…

  • 失败了的罗永浩

    失败了的罗永浩73人支持

    这段时间一直被罗永浩的各种消息所席卷。此人一直站在商业领域的最前沿,从锤子手机到玩电子烟,业务不断失败。现在不仅欠了一笔债,还被丹阳市人民法院列入失信人黑名单,限制高消…