Redis 地理空間(geospatial)介紹及應用

_天道酬勤_發表於2020-04-04

簡介

Redis在3.2版本中加入了地理空間(geospatial)以及索引半徑查詢的功能

主要用在需要地理位置的應用上

將指定的地理空間位置(緯度、經度、名稱)新增到指定的key中。這些資料將會儲存到sorted set這樣的目的是為了方便使用GEORADIUS或者GEORADIUSBYMEMBER命令對資料進行半徑查詢等操作

工作原理

它是如何工作的?

sorted set使用一種稱為Geohash的技術進行填充。經度和緯度的位是交錯的,以形成一個獨特的52位整數. 我們知道,一個sorted set 的double score可以代表一個52位的整數,而不會失去精度。

這種格式允許半徑查詢檢查的1 + 8個領域需要覆蓋整個半徑,並丟棄元素以外的半徑。通過計算該區域的範圍,通過計算所涵蓋的範圍,從不太重要的部分的排序集的得分,並計算得分範圍為每個區域的sorted set中的查詢。

使用什麼樣的地球模型(Earth model)?

這只是假設地球是一個球體,因為使用的距離公式是Haversine公式。這個公式僅適用於地球,而不是一個完美的球體。當在社交網站和其他大多數需要查詢半徑的應用中使用時,這些偏差都不算問題。但是,在最壞的情況下的偏差可能是0.5%,所以一些地理位置很關鍵的應用還是需要謹慎考慮。

命令說明

GEOADD

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

時間複雜度: O(log(N)), N為member的數量

功能說明: 將指定的地理空間位置(緯度、經度、名稱)新增到指定的key中。這些資料將會儲存到sorted set這樣的目的是為了方便使用GEORADIUS或者GEORADIUSBYMEMBER命令對資料進行半徑查詢等操作

返回值: 整數,新增到sorted set元素的數目,但不包括已更新score的元素

示例

GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669

注意

該命令以採用標準格式的引數x,y,所以經度必須在緯度之前。這些座標的限制是可以被編入索引的,區域面積可以很接近極點但是不能索引。具體的限制,由EPSG:900913 / EPSG:3785 / OSGEO:41001 規定如下:

有效的經度從-180度到180度。 有效的緯度從-85.05112878度到85.05112878度。 當座標位置超出上述指定範圍時,該命令將會返回一個錯誤。

GEODIST

GEODIST key member1 member2 [unit]

時間複雜度: O(log(N))

功能說明

  • 返回兩個給定位置之間的距離,如果兩個位置之間的其中一個不存在, 那麼命令返回空值。
  • 指定單位的引數 unit 必須是以下單位的其中一個:
    • m 表示單位為米(預設值)
    • km 表示單位為千米
    • mi 表示單位為英里
    • ft 表示單位為英尺

返回值: 計算出的距離會以雙精度浮點數的形式被返回。 如果給定的位置元素不存在, 那麼命令返回空值

示例: GEODIST Sicily Palermo Catania km

GEOHASH

GEOHASH key member [member ...]

時間複雜度: O(log(N)), N 為member的數量

功能說明

  • 返回一個或多個位置元素的 Geohash 表示
  • 通常使用表示位置的元素使用不同的技術,使用Geohash位置52點整數編碼。由於編碼和解碼過程中所使用的初始最小和最大座標不同,編碼的編碼也不同於標準。此命令返回一個標準的Geohash,在維基百科和geohash.org網站都有相關描述

返回值

一個陣列, 陣列的每個項都是一個 geohash 。 命令返回的 geohash 的位置與使用者給定的位置元素的位置一一對應

示例: GEOHASH Sicily Palermo Catania

GEOPOS

GEOPOS key member [member ...]

時間複雜度: O(log(N))

功能說明: 從key裡返回所有給定位置元素的位置(經度和緯度)

返回值

GEOPOS 命令返回一個陣列, 陣列中的每個項都由兩個元素組成: 第一個元素為給定位置元素的經度, 而第二個元素則為給定位置元素的緯度。

當給定的位置元素不存在時, 對應的陣列項為空值

GEORADIUS

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

時間複雜度: O(N+log(M)),其中N是圓形區域的邊界框內的元素數,該元素由中心和半徑定界,M是索引內的項數

功能說明

以給定的經緯度為中心, 返回鍵包含的位置元素當中,與中心的距離不超過給定最大距離的所有位置元素

範圍可以使用以下其中一個單位:

  • m 表示單位為米。
  • km 表示單位為千米。
  • mi 表示單位為英里。
  • ft 表示單位為英尺。

在給定以下可選項時, 命令會返回額外的資訊:

WITHDIST

在返回位置元素的同時, 將位置元素與中心之間的距離也一併返回。 距離的單位和使用者給定的範圍單位保持一致。

WITHCOORD

將位置元素的經度和維度也一併返回。

WITHHASH

以 52 位有符號整數的形式, 返回位置元素經過原始 geohash 編碼的有序集合分值。 這個選項主要用於底層應用或者除錯, 實際中的作用並不大。 命令預設返回未排序的位置元素。

通過以下兩個引數, 使用者可以指定被返回位置元素的排序方式:

ASC: 根據中心的位置, 按照從近到遠的方式返回位置元素。

DESC: 根據中心的位置, 按照從遠到近的方式返回位置元素。

在預設情況下, GEORADIUS 命令會返回所有匹配的位置元素。 雖然使用者可以使用 COUNT 選項去獲取前 N 個匹配元素, 但是因為命令在內部可能會需要對所有被匹配的元素進行處理, 所以在對一個非常大的區域進行搜尋時, 即使只使用 COUNT 選項去獲取少量元素, 命令的執行速度也可能會非常慢。 但是從另一方面來說, 使用 COUNT 選項去減少需要返回的元素數量, 對於減少頻寬來說仍然是非常有用的。

返回值

在沒有給定任何 WITH 選項的情況下, 命令只會返回一個像 [“New York”,”Milan”,”Paris”] 這樣的線性(linear)列表。

在指定了 WITHCOORD 、 WITHDIST 、 WITHHASH 等選項的情況下, 命令返回一個二層巢狀陣列, 內層的每個子陣列就表示一個元素。 在返回巢狀陣列時, 子陣列的第一個元素總是位置元素的名字。

至於額外的資訊, 則會作為子陣列的後續元素, 按照以下順序被返回:

  1. 以浮點數格式返回的中心與位置元素之間的距離, 單位與使用者指定範圍時的單位一致
  2. geohash 整數。由兩個元素組成的座標,分別為經度和緯度
  3. 由兩個元素組成的座標,分別為經度和緯度

GEORADIUSBYMEMBER

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

時間複雜度: O(N+log(M)),其中N是圓形區域的邊界框內的元素數,該元素由中心和半徑界定,M是索引內的項數。

功能說明: 這個命令和 GEORADIUS 命令一樣, 都可以找出位於指定範圍內的元素, 但是 GEORADIUSBYMEMBER 的中心點是由給定的位置元素決定的, 而不是像 GEORADIUS 那樣, 使用輸入的經度和緯度來決定中心點指定成員的位置被用作查詢的中心

參考資料

Redis geospatial 說明

相關文章