GEOADD keylongitude latitude member [longitude latitude member ...]

Available since 3.2.0.

Time complexity: O(log(N)) for each item added, where N is the number of elements in the sorted set.

Adds the specified geospatial items (latitude, longitude, name) to the specified key. Data is stored into the key as a sorted set, in a way that makes it possible to later retrieve items using a query by radius with the GEORADIUS or GEORADIUSBYMEMBER commands.

The command takes arguments in the standard format x,y so the longitude must be specified before the latitude. There are limits to the coordinates that can be indexed: areas very near to the poles are not indexable. The exact limits, as specified by EPSG:900913 / EPSG:3785 / OSGEO:41001 are the following:

  • Valid longitudes are from -180 to 180 degrees.
  • Valid latitudes are from -85.05112878 to 85.05112878 degrees.

The command will report an error when the user attempts to index coordinates outside the specified ranges.

Note: there is no GEODEL command because you can use ZREM in order to remove elements. The Geo index structure is just a sorted set.

How does it work?

The way the sorted set is populated is using a technique called Geohash. Latitude and Longitude bits are interleaved in order to form an unique 52 bit integer. We know that a sorted set double score can represent a 52 bit integer without losing precision.

This format allows for radius querying by checking the 1+8 areas needed to cover the whole radius, and discarding elements outside the radius. The areas are checked by calculating the range of the box covered removing enough bits from the less significant part of the sorted set score, and computing the score range to query in the sorted set for each area.

What Earth model does it use?

It just assumes that the Earth is a sphere, since the used distance formula is the Haversine formula. This formula is only an approximation when applied to the Earth, which is not a perfect sphere. The introduced errors are not an issue when used in the context of social network sites that need to query by radius and most other applications. However in the worst case the error may be up to 0.5%, so you may want to consider other systems for error-critical applications.

Return value

Integer reply, specifically:

  • The number of elements added to the sorted set, not including elements already existing for which the score was updated.

Examples

redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"

(integer) 2

redis> GEODIST Sicily Palermo Catania

"166274.1516"

redis> GEORADIUS Sicily 15 37 100 km

1) "Catania"

redis> GEORADIUS Sicily 15 37 200 km

1) "Palermo"
2) "Catania"

redis>

翻译:

自3.2.0起可用。

每个添加项目的时间复杂度: O(log(N)),其中N是排序集中的元素数。

将指定的地理空间项目(纬度,经度,名称)添加到指定的键。数据作为排序集存储到密钥中,使得可以使用GEORADIUSGEORADIUSBYMEMBER命令使用半径查询稍后检索项目。

该命令采用标准格式x,y的参数,因此必须在纬度之前指定经度。可以索引的坐标有限制:非常靠近极点的区域不可索引。如EPSG:900913 / EPSG:3785 / OSGEO:41001规定的具体限值如下:

  • 有效经度为-180至180度。
  • 有效纬度为-85.05112878至85.05112878度。

当用户尝试对指定范围之外的坐标进行索引时,该命令将报告错误。

注意:没有GEODEL命令,因为您可以使用ZREM来删除元素。地理索引结构只是一个排序集。

它是如何工作的?

排序集的填充方式是使用名为Geohash的技术 。纬度和经度位被交织,以便形成唯一的52位整数。我们知道一个排序集合的双分可以代表一个52位整数,而不会失去精度。

该格式允许通过检查覆盖整个半径所需的1 + 8区域,并丢弃半径外的元素来进行半径查询。通过计算被覆盖的区域的范围来检查区域,从排序的设定分数的较不重要的部分中移除足够的位,并且计算每个区域的排序集合中的查询的得分范围。

它使用什么地球模型?

它只是假设地球是一个球体,因为使用的距离公式是Haversine公式。这个公式只适用于地球的近似值,这不是一个完美的球体。当在需要通过半径和大多数其他应用程序查询的社交网站的上下文中使用时,引入的错误不是问题。然而,在最坏的情况下,错误可能高达0.5%,因此您可能需要考虑其他系统的错误关键应用程序。

返回值

整数回复,具体来说:

  • 添加到排序集中的元素数量,不包括已更新分数的元素

geoadd

geoadd用来增加地理位置的坐标,可以批量添加地理位置,命令格式为:

GEOADD key longitude latitude member [longitude latitude member ...]

key标识一个地理位置的集合。longitude latitude member标识了一个地理位置的坐标。longitude是地理位置的经度,latitude是地理位置的纬度。member是该地理位置的名称。GEOADD可以批量给集合添加一批地理位置。

geopos

geopos可以获取地理位置的坐标,可以批量获取多个地理位置的坐标,命令格式为:

GEOPOS key member [member ...]

geodist

geodist用来获取两个地理位置的距离,命令格式为:

GEODIST key member1 member2 [m|km|ft|mi]

单位可以指定为以下四种类型:

  • m:米,距离单位默认为米,不传递该参数则单位为米。
  • km:公里。
  • mi:英里。
  • ft:英尺。

georadius

georadius可以根据给定地理位置坐标获取指定范围内的地理位置集合。命令格式为:

GEORADIUS key longitude latitude radius [m|km|ft|mi] [WITHCOORD] [WITHDIST] [ASC|DESC] [WITHHASH] [COUNT count]

longitude latitude标识了地理位置的坐标,radius表示范围距离,距离单位可以为m|km|ft|mi,还有一些可选参数:

  • WITHCOORD:传入WITHCOORD参数,则返回结果会带上匹配位置的经纬度。
  • WITHDIST:传入WITHDIST参数,则返回结果会带上匹配位置与给定地理位置的距离。
  • ASC|DESC:默认结果是未排序的,传入ASC为从近到远排序,传入DESC为从远到近排序。
  • WITHHASH:传入WITHHASH参数,则返回结果会带上匹配位置的hash值。
  • COUNT count:传入COUNT参数,可以返回指定数量的结果。

georadiusbymember

georadiusbymember可以根据给定地理位置获取指定范围内的地理位置集合。georadius命令传递的是坐标,georadiusbymember传递的是地理位置。georadius更为灵活,可以获取任何坐标点范围内的地理位置。但是大多数时候,只是想获取某个地理位置附近的其他地理位置,使用georadiusbymember则更为方便。georadiusbymember命令格式为(命令可选参数与georadius含义一样):

GEORADIUSBYMEMBER key member radius [m|km|ft|mi] [WITHCOORD] [WITHDIST] [ASC|DESC] [WITHHASH] [COUNT count]

geohash

geohash可以获取某个地理位置的geohash值。geohash是将二维的经纬度转换成字符串hash值的算法,后面会具体介绍geohash原理。可以批量获取多个地理位置的geohash值。命令格式为:

GEOHASH key member [member ...]

redis GEO实现

redis GEO实现主要包含了以下两项技术:

  • 1、使用geohash保存地理位置的坐标。
  • 2、使用有序集合(zset)保存地理位置的集合。

geohash

geohash的思想是将二维的经纬度转换成一维的字符串,geohash有以下三个特点:

  • 1、字符串越长,表示的范围越精确。编码长度为8时,精度在19米左右,而当编码长度为9时,精度在2米左右。
  • 2、字符串相似的表示距离相近,利用字符串的前缀匹配,可以查询附近的地理位置。这样就实现了快速查询某个坐标附近的地理位置。
  • 3、geohash计算的字符串,可以反向解码出原来的经纬度。

这三个特性让geohash特别适合表示二维hash值。这篇文章:GeoHash核心原理解析详细的介绍了geohash的原理,想要了解geohash实现的朋友可以参考这篇文章。

redis GEO命令实现

知道了redis使用有序集合(zset)保存地理位置数据(想了解redis有序集合的,可以参看这篇文章《有序集合对象》),以及geohash的特性,就很容易理解redis是如何实现redis GEO命令了。细心的读者可能发现,redis没有实现地理位置的删除命令。不过由于GEO数据保存在zset中,可以用zrem来删除某个地理位置。

  • geoadd命令增加地理位置的时候,会先计算地理位置坐标的geohash值,然后地理位置作为有序集合的member,geohash作为该member的score。然后使用zadd命令插入到有序集合。
  • geopos命令则先根据地理位置获取geohash值,然后decode得到地理位置的坐标。
  • geodist命令先根据两个地理位置各自得到坐标,然后计算两个坐标的距离。
  • georadius和georadiusbymember使用相同的实现,georadiusbymember多了一步把地理位置转换成对应的坐标。然后查找该坐标和周围对应8个坐标符合距离要求的地理位置。因为geohash得到的值其实是个格子,并不是点,这样通过计算周围对应8个坐标就能解决边缘问题。由于使用有序集合保存地理位置,在对地列位置基于范围查询,就相当于实现了zrange命令,内部的实现确实与zrange命令一致,只是geo有些特别的处理,比如获得的某个地理位置,还需要计算该地理位置是否符合给定的距离访问。
  • geohash则直接返回了地理位置的geohash值。

redis关于geohash使用了Ardb的geohash库geohash-int,redis使用的geohash编码长度为26位。可以精确到0.59m的精度。

总结

通过本文,拨开GEO身后的云雾,可以看出redis借助了有序集合(zset)和geohash,加上redis本身实现的命令框架,可以很容易的实现地理位置相关的命令。

参考文献:

redis GEO地理位置命令介绍的更多相关文章

  1. redis3.2新功能--GEO地理位置命令介绍

    概述 redis3.2发布rc版本已经有一段时间了,估计RedisConf 2016左右,3.2版本就能release了.3.2版本中增加的最大功能就是对GEO(地理位置)的支持.说起redis的GE ...

  2. 【转】redis GEO地理位置

    redis目前已经到了3.2版本,3.2版本里面新增的一个功能就是对GEO(地理位置)的支持. 地理位置大概提供了6个命令,分别为: GEOADD GEODIST GEOHASH GEOPOS GEO ...

  3. Redis GEO 地理位置

    目录 GEO指令 GEOADD GEODIST GEOPOP GEOHASH GEORADIUS GEORADIUSBYMEMBER 指令补充 删除操作 避免单集合数量过多 存储原理 GEOADD存储 ...

  4. Redis Geo HyperLogLog类型介绍

    ​Geo类型 Redis3.2.0版本推出 可以将用户给定的地理位置信息存储起来,并对这些信息进行操作 GEOADD key longitude latitude member [longitude ...

  5. Redis GEO地理位置信息,查看附近的人

    在之前的一篇文章<SpringBoot入门教程(五)Java基于MySQL实现附近的人>,我们介绍了Java基于MySQL实现查找附近的人的功能.今天就来研究研究"查找附近的人& ...

  6. redis事务及相关命令介绍

    redis事务及相关命令介绍 一.概述:和众多其它数据库一样,Redis作为NoSQL数据库也同样提供了事务机制.在Redis中,MULTI/EXEC/DISCARD/WATCH这四个命令是我们实现事 ...

  7. Redis GEO 功能使用场景

    本文来源:https://www.dazhuanlan.com/2020/02/05/5e3a0a3110649/ 背景 前段时间自己在做附近直播相关业务,其中有一个核心的点就是检索用户附近的主播,也 ...

  8. Redis计算地理位置距离-GeoHash

    Redis 在 3.2 版本以后增加了地理位置 GEO 模块,意味着我们可以使用 Redis 来实现摩拜单车「附近的 Mobike」.美团和饿了么「附近的餐馆」这样的功能了. 地图元素的位置数据使用二 ...

  9. redis GEO的使用

    一.概念 redis的GEO特性在Redis3.2版本发布,这个功能可以将用户给定的地理位置信息储存起来,并对这些信息进行操作. GEO常用语LBS(Location Based Service),基 ...

随机推荐

  1. PAT 天梯赛 L3-001. 凑零钱 【DP】【DFS】

    题目链接 https://www.patest.cn/contests/gplt/L3-001 思路 DP[I][J] I 表示第几个物品 J 表示多少钱 dp[i][j] 为 bool 值 表示 当 ...

  2. ubuntu14.04搭建gitlab

    以下内容来自:https://mirror.tuna.tsinghua.edu.cn/help/gitlab-ce/  (清华大学开源软件镜像站)可以直接移步上面的网站.这里做个笔记,也是为了记录一下 ...

  3. [转]Mysql命令

    1.连接Mysql 格式: mysql -h主机地址 -u用户名 -p用户密码 1.连接到本机上的MYSQL.首先打开DOS窗口,然后进入目录mysql\bin,再键入命令mysql -u root ...

  4. [算法]在数组中找到出现次数大于N/K的数

    题目: 1.给定一个整型数组,打印其中出现次数大于一半的数.如果没有出现这样的数,打印提示信息. 如:1,2,1输出1.    1,2,3输出no such number. 2.给定一个整型数组,再给 ...

  5. poj 1065 Wooden Sticks 【贪心 新思维】

    题目地址:http://poj.org/problem?id=1065 Sample Input 3 5 4 9 5 2 2 1 3 5 1 4 3 2 2 1 1 2 2 3 1 3 2 2 3 1 ...

  6. 如何拯救一台glibc被干掉的Linux服务器

    原文: 如何拯救一台glibc被干掉的Linux服务器? 首先如果 libc.so.6 没有被删除, 直接使用LD_PRELOAD就可以恢复 LD_PRELOAD=/lib64/libc-2.12.s ...

  7. linux安全相关

    2017-05-11突然谈到linux安全相关的话题,记录一下 搜了一下,找到一篇介绍apparmor和selinux的文章 http://www.361way.com/apparmor-selinu ...

  8. CV2图像操作

    一.读入图像使用函数cv2.imread(filepath,flags)读入一副图片filepath:要读入图片的完整路径flags:读入图片的标志 cv2.IMREAD_COLOR:默认参数,读入一 ...

  9. 仿联想商城laravel实战---7、lavarel中如何给用户发送邮件

    仿联想商城laravel实战---7.lavarel中如何给用户发送邮件 一.总结 一句话总结: 设置邮件服务器,比如163邮箱 lavarel中配置邮件服务,在.env中 控制器中使用Mail对象发 ...

  10. html网页小图标

    <link rel="shortcut icon" href="../image/favicon.ico"/>