最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Redis中地理位置功能Geospatial的應用

 更新時間:2023年06月01日 09:46:04   作者:蜀山劍客李沐白  
Geospatial?Indexes?是?Redis?提供的一種數(shù)據結構,用于存儲和查詢地理位置信息,這篇文章就來和大家詳細講講Geospatial的具體應用吧

Geospatial Indexes 是 Redis 提供的一種數(shù)據結構,用于存儲和查詢地理位置信息。它可以將地理位置的經度和緯度編碼為二維平面上的點,并支持根據距離或矩形區(qū)域查詢附近的地理位置點,這使得它在很多場景下被廣泛應用,比如 LBS(Location Based Service)、智能推薦、出行規(guī)劃等。

Redis 中 Geospatial Indexes 是通過有序集合實現(xiàn)的,其內部使用 zset 數(shù)據類型來存儲地理位置點的經緯度和成員信息。其中,經緯度以浮點數(shù)表示,成員信息則可以是用戶 ID、商鋪名稱等。

在使用 Geospatial Indexes 時,我們需要注意以下幾個方面:

  • 地理位置點的經緯度采用 WGS-84 坐標系表示;
  • 距離單位默認為米,可以通過參數(shù)設置為其他單位;
  • 矩形區(qū)域查詢默認采用左閉右開的方式,即包括左邊界,不包括右邊界。

Geospatial Indexes 的數(shù)據結構

Geospatial Indexes 在 Redis 中是通過 zset 實現(xiàn)的,其中地理位置點的經緯度被編碼為 zset 中每個 member 的分數(shù)。具體來說,Redis 在將經緯度編碼為分數(shù)時,使用了 zset 的有序性質,將其轉化為一個唯一的、不可重復的浮點數(shù)。

例如,如果我們要存儲以下三個地理位置點:

39.9042° N, 116.4074° E
上海 31.2304° N, 121.4737° E
廣州 23.1291° N, 113.2644° E

則可以將經緯度編碼為分數(shù),存入 zset 中,如下圖所示:

ZADD city_geo_location 116.4074 39.9042 "北京"
ZADD city_geo_location 121.4737 31.2304 "上海"
ZADD city_geo_location 113.2644 23.1291 "廣州"

此時,zset 中的每個 member 都代表了一個地理位置點,其分數(shù)則代表了該點的唯一標識,在進行距離或矩形區(qū)域查詢時將會用到。

常用命令

Redis 中的 Geospatial Indexes 提供了一組命令來管理和查詢地理位置數(shù)據,包括以下命令:

1.GEOADD:向有序集合中添加一個或多個地理位置元素。

語法:GEOADD key longitude latitude member [longitude latitude member ...]

參數(shù):

  • key:必需,要添加元素的有序集合的鍵名。
  • longitude:必需,要添加元素的經度值,范圍為 -180 到 180 度。
  • latitude:必需,要添加元素的緯度值,范圍為 -90 到 90 度。
  • member:必需,要添加元素的成員名,必須為字符串類型。

示例:GEOADD restaurants 139.7329 35.6634 "Sushi Dai" 139.7712 35.7100 "Afuri Ramen" 139.7198 35.7101 "Komoro Soba"

2.GEOPOS:獲取指定成員在有序集合中的經緯度坐標。

語法:GEOPOS key member [member ...]

參數(shù):

  • key:必需,要獲取經緯度坐標的有序集合的鍵名。
  • member:必需,要獲取經緯度坐標的元素的成員名,可以指定多個成員名。

返回值:一個二維數(shù)組,每個子數(shù)組表示一個成員的經緯度坐標,每個子數(shù)組包含兩個元素,分別表示經度和緯度。

示例:GEOPOS restaurants "Sushi Dai" "Komoro Soba",返回值為 [["139.7329","35.6634"],["139.7198","35.7101"]]

3.GEODIST:獲取有序集合中兩個成員之間的距離。

語法:GEODIST key member1 member2 [unit]

參數(shù):

  • key:必需,要計算距離的有序集合的鍵名。
  • member1:必需,第一個成員的名字。
  • member2:必需,第二個成員的名字。
  • unit:可選,默認為米,表示要返回的距離單位,可以是以下四種單位之一:"m"(米)、"km"(千米)、"mi"(英里)、"ft"(英尺)。

返回值:兩個成員之間的距離值,以指定的單位表示。

示例:GEODIST restaurants "Sushi Dai" "Komoro Soba" km,返回值為 "2.0499"

4.GEORADIUS:按照給定的經緯度坐標和半徑范圍查找有序集合中符合條件的元素。

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

參數(shù):

  • key:必需,要查詢的有序集合的鍵名。
  • longitude:必需,中心點的經度值,范圍為 -180 到 180 度。
  • latitude:必需,中心點的緯度值,范圍為 -90 到 90 度。
  • radius:必需,半徑范圍,可以是以下格式之一:m(米)、km(千米)、mi(英里)或 ft(英尺)。
  • m|km|mi|ft:必需,半徑范圍的單位,可以是以下四種單位之一:"m"(米)、"km"(千米)、"mi"(英里)、"ft"(英尺)。
  • WITHCOORD:可選,指示返回結果是否包含元素的經緯度坐標。如果指定了該參數(shù),則結果將包含經緯度坐標,否則不包含經緯度坐標。
  • WITHDIST:可選,指示返回結果是否包含元素與中心點之間的距離值。如果指定了該參數(shù),則結果將包含距離值,否則不包含距離值。
  • ASC|DESC:可選,指示返回結果是否按照距離值(從小到大)排序。如果指定了該參數(shù),則結果將按距離值排序,否則默認按有序集合中的順序返回結果。
  • COUNT count:可選,指示返回結果的數(shù)量限制。如果指定了該參數(shù),則結果將最多包含 count 個元素,否則返回所有符合條件的元素。

返回值:若干個符合條件的元素(根據查詢參數(shù)而定),每個元素由成員名、經度坐標和緯度坐標組成。如果指定了 WITHDIST 參數(shù),則每個元素還包含距離值。如果指定了 WITHCOORD 參數(shù),則每個元素還包含經緯度坐標。

示例:GEORADIUS restaurants 139.7329 35.6634 5 km WITHCOORD WITHDIST,表示查找以經緯度 (139.7329, 35.6634) 為中心,半徑為 5 公里范圍內的所有元素,并返回它們與中心點之間的距離值和經緯度坐標。

5.GEORADIUSBYMEMBER:按照給定的成員名和半徑范圍查找有序集合中符合條件的元素。

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

參數(shù):

  • key:必需,要查詢的有序集合的鍵名。
  • member:必需,中心點的成員名。
  • radius:必需,半徑范圍,可以是以下格式之一:m(米)、km(千米)、mi(英里)或 ft(英尺)
  • m|km|mi|ft:必需,半徑范圍的單位,可以是以下四種單位之一:"m"(米)、"km"(千米)、"mi"(英里)、"ft"(英尺)。
  • WITHCOORD:可選,指示返回結果是否包含元素的經緯度坐標。如果指定了該參數(shù),則結果將包含經緯度坐標,否則不包含經緯度坐標。
  • WITHDIST:可選,指示返回結果是否包含元素與中心點之間的距離值。如果指定了該參數(shù),則結果將包含距離值,否則不包含距離值。
  • ASC|DESC:可選,指示返回結果是否按照距離值(從小到大)排序。如果指定了該參數(shù),則結果將按距離值排序,否則默認按有序集合中的順序返回結果。
  • COUNT count:可選,指示返回結果的數(shù)量限制。如果指定了該參數(shù),則結果將最多包含 count 個元素,否則返回所有符合條件的元素。

返回值:若干個符合條件的元素(根據查詢參數(shù)而定),每個元素由成員名、經度坐標和緯度坐標組成。如果指定了 WITHDIST 參數(shù),則每個元素還包含距離值。如果指定了 WITHCOORD 參數(shù),則每個元素還包含經緯度坐標。

示例:GEORADIUSBYMEMBER restaurants "Sushi Dai" 5 km WITHCOORD WITHDIST,表示查找以成員名 "Sushi Dai" 對應的經緯度為中心,半徑為 5 公里范圍內的所有元素,并返回它們與中心點之間的距離值和經緯度坐標。

6.GEOHASH:獲取指定成員在有序集合中的 Geohash 值。

語法:GEOHASH key member [member ...]

參數(shù):

  • key:必需,要獲取 Geohash 值的有序集合的鍵名。
  • member:必需,要獲取 Geohash 值的元素的成員名,可以指定多個成員名。

返回值:一個數(shù)組,每個元素表示一個成員的 Geohash 值。

示例:GEOHASH restaurants "Sushi Dai" "Komoro Soba",返回值為 ["xn7743","xn773w"]

7.GEOINTERSECTS:檢查指定的兩個成員之間是否存在任何交集。

語法:GEOINTERSECTS key member1 member2

參數(shù):

  • key:必需,要檢查交集的有序集合的鍵名。
  • member1:必需,第一個成員的名字。
  • member2:必需,第二個成員的名字。

返回值:一個整數(shù)值,如果兩個成員之間存在交集,則返回 1,否則返回 0。

示例:GEOINTERSECTS restaurants "Sushi Dai" "Komoro Soba",如果 "Sushi Dai" 和 "Komoro Soba" 代表的位置之間存在任何交集,則返回 1,否則返回 0。

實用場景示例

1. 找出某一經緯度周圍的餐館

import redis.clients.jedis.GeoRadiusResponse;
import redis.clients.jedis.GeoUnit;
import redis.clients.jedis.Jedis;
import java.util.List;
public class RestaurantFinder {
    private final static String HOST = "localhost";
    private final static int PORT = 6379;
    private final static int TIMEOUT = 5000;
    private final static String PASSWORD = "";
    private static final String KEY_RESTAURANT_LOCATION = "restaurant_location";
    private static Jedis jedis = null;
    static {
        try {
            jedis = new Jedis(HOST, PORT, TIMEOUT);
            if (!PASSWORD.isEmpty()) {
                jedis.auth(PASSWORD);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 添加餐館的經緯度信息
     *
     * @param longitude 經度
     * @param latitude  緯度
     * @param name      餐館名稱
     * @return
     */
    public Long addRestaurant(double longitude, double latitude, String name) {
        return jedis.geoadd(KEY_RESTAURANT_LOCATION, longitude, latitude, name);
    }
    /**
     * 根據給定的坐標和半徑查找周圍的餐館
     *
     * @param longitude 經度
     * @param latitude  緯度
     * @param radius    半徑,單位為米
     * @return
     */
    public List<GeoRadiusResponse> findNearbyRestaurants(double longitude, double latitude, double radius) {
        return jedis.georadius(KEY_RESTAURANT_LOCATION, longitude, latitude, radius, GeoUnit.M);
    }
    /**
     * 測試
     *
     * @param args
     */
    public static void main(String[] args) {
        RestaurantFinder finder = new RestaurantFinder();
        finder.addRestaurant(121.451087, 31.228591, "麥當勞");
        finder.addRestaurant(121.454987, 31.227568, "星巴克");
        finder.addRestaurant(121.455831, 31.225719, "肯德基");
        List<GeoRadiusResponse> restaurants = finder.findNearbyRestaurants(121.453289, 31.228032, 500);
        for (GeoRadiusResponse restaurant : restaurants) {
            System.out.println(restaurant.getMemberByString() + " " + restaurant.getDistance());
        }
    }
}

2. 按照距離排序查詢景點

import redis.clients.jedis.GeoRadiusParam;
import redis.clients.jedis.GeoRadiusResponse;
import redis.clients.jedis.GeoUnit;
import redis.clients.jedis.Jedis;
import java.util.List;
public class ScenicSpotFinder {
    private final static String HOST = "localhost";
    private final static int PORT = 6379;
    private final static int TIMEOUT = 5000;
    private final static String PASSWORD = "";
    private static final String KEY_SPOT_LOCATION = "spot_location";
    private static Jedis jedis = null;
    static {
        try {
            jedis = new Jedis(HOST, PORT, TIMEOUT);
            if (!PASSWORD.isEmpty()) {
                jedis.auth(PASSWORD);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 添加景點的經緯度信息
     *
     * @param longitude 經度
     * @param latitude  緯度
     * @param name      景點名稱
     * @return
     */
    public Long addScenicSpot(double longitude, double latitude, String name) {
        return jedis.geoadd(KEY_SPOT_LOCATION, longitude, latitude, name);
    }
    /**
     * 根據給定的坐標和半徑查找周圍的景點,并按照距離排序
     *
     * @param longitude 經度
     * @param latitude  緯度
     * @param radius    半徑,單位為米
     * @return
     */
    public List<GeoRadiusResponse> findNearbyScenicSpots(double longitude, double latitude, double radius) {
        GeoRadiusParam geoRadiusParam = GeoRadiusParam.geoRadiusParam().sortAscending();
        return jedis.georadius(KEY_SPOT_LOCATION, longitude, latitude, radius, GeoUnit.M, geoRadiusParam);
    }
    /**
     * 測試
     *
     * @param args
     */
    public static void main(String[] args) {
        ScenicSpotFinder finder = new ScenicSpotFinder();
        finder.addScenicSpot(121.451087, 31.228591, "東方明珠");
        finder.addScenicSpot(121.454987, 31.227568, "外灘");
        finder.addScenicSpot(121.455831, 31.225719, "人民廣場");
        List<GeoRadiusResponse> spots = finder.findNearbyScenicSpots(121.453289, 31.228032, 500);
        for (GeoRadiusResponse spot : spots) {
            System.out.println(spot.getMemberByString() + " " + spot.getDistance());
        }
    }
}

3. 根據經緯度計算兩點距離

import redis.clients.jedis.GeoUnit;
import redis.clients.jedis.Jedis;
public class DistanceCalculator {
    private final static String HOST = "localhost";
    private final static int PORT = 6379;
    private final static int TIMEOUT = 5000;
    private final static String PASSWORD = "";
    private static Jedis jedis = null;
    static {
        try {
            jedis = new Jedis(HOST, PORT, TIMEOUT);
            if (!PASSWORD.isEmpty()) {
                jedis.auth(PASSWORD);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 計算兩個經緯度之間的距離
     *
     * @param longitude1 經度1
     * @param latitude1  緯度1
     * @param longitude2 經度2
     * @param latitude2  緯度2
     * @return
     */
    public Double calculateDistance(double longitude1, double latitude1, double longitude2, double latitude2) {
        return jedis.geodist("distance", longitude1, latitude1, longitude2, latitude2, GeoUnit.M);
    }
    /**
     * 測試
     *
     * @param args
     */
    public static void main(String[] args) {
        DistanceCalculator calculator = new DistanceCalculator();
        double distance = calculator.calculateDistance(121.453289, 31.228032, 121.451087, 31.228591);
        System.out.println(distance);
    }
}

在實際開發(fā)中,需要注意以下幾點:

  • 每個位置都需要一個唯一的標識符。
  • 經度和緯度的值需要使用正確的格式。
  • 半徑的單位為米。
  • Redis 地理位置功能支持多種查詢方式,例如矩形查詢、關鍵字查詢等,需要根據實際需求進行選擇。

以上就是詳解Redis中地理位置功能Geospatial的應用的詳細內容,更多關于Redis Geospatial的資料請關注腳本之家其它相關文章!

相關文章

  • 搭建Caffeine+Redis多級緩存機制

    搭建Caffeine+Redis多級緩存機制

    本文主要介紹了搭建Caffeine+Redis多級緩存機制,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-07-07
  • Redis哨兵模式實現(xiàn)一主二從三哨兵

    Redis哨兵模式實現(xiàn)一主二從三哨兵

    本文主要介紹了Redis哨兵模式實現(xiàn)一主二從三哨兵,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-07-07
  • redis.config配置文件

    redis.config配置文件

    在使用Redis時,我們通常需要對Redis進行一些配置,以確保其能夠正常運行并滿足我們的需求,本文主要介紹了redis.config配置文件,感興趣的可以了解一下
    2023-11-11
  • Linux、Windows下Redis的安裝即Redis的基本使用詳解

    Linux、Windows下Redis的安裝即Redis的基本使用詳解

    Redis是一個基于內存的key-value結構數(shù)據庫,Redis 是互聯(lián)網技術領域使用最為廣泛的存儲中間件,這篇文章主要介紹了Linux、Windows下Redis的安裝即Redis的基本使用詳解,需要的朋友可以參考下
    2022-09-09
  • Window server中安裝Redis的超詳細教程

    Window server中安裝Redis的超詳細教程

    這篇文章主要介紹了Window server中安裝Redis的教程,本文通過圖文實例代碼相結合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-11-11
  • Redis緩存預熱的概念及方法詳解

    Redis緩存預熱的概念及方法詳解

    文章解釋了什么是緩存預熱,為什么邏輯過期必須預熱,并提供了三種簡單的方法來實現(xiàn)緩存預熱,同時介紹了saveShop2Redis方法的作用和角色,感興趣的朋友跟隨小編一起看看吧
    2026-04-04
  • Redis配置文件redis.conf詳細配置說明

    Redis配置文件redis.conf詳細配置說明

    本文列出了Redis的配置文件redis.conf的各配置項的詳細說明,簡單易懂
    2018-03-03
  • redis隊列和秒殺應用方式

    redis隊列和秒殺應用方式

    這篇文章主要介紹了redis隊列和秒殺應用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • redis如何取hash的值

    redis如何取hash的值

    這篇文章主要介紹了redis如何取hash的值問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • Redis超詳細分析分布式鎖

    Redis超詳細分析分布式鎖

    在單體應用中,如果我們對共享數(shù)據不進行加鎖操作,會出現(xiàn)數(shù)據一致性問題,我們的解決辦法通常是加鎖。下面我們一起聊聊使用redis來實現(xiàn)分布式鎖
    2022-07-07

最新評論

肥乡县| 同德县| 沙坪坝区| 宜黄县| 涟水县| 桃源县| 萍乡市| 桐庐县| 皋兰县| 衢州市| 通海县| 垣曲县| 晋城| 祥云县| 贵定县| 永州市| 河间市| 澎湖县| 宜章县| 东乌| 兴安盟| 开化县| 谷城县| 福贡县| 望城县| 益阳市| 孟连| 忻城县| 津市市| 东光县| 大厂| 辛集市| 滦南县| 朝阳县| 固原市| 桓仁| 吉首市| 临汾市| 平舆县| 曲周县| 辰溪县|