redis GEO數(shù)據(jù)結(jié)構(gòu)、實(shí)現(xiàn)附近商鋪功能實(shí)踐
一、GEO
Grolocation意為地理坐標(biāo),允許存儲(chǔ)地理坐標(biāo)信息,完成地理坐標(biāo)之間距離的計(jì)算。
geoadd key longitude1 latitude1 field1 longitude2 latitude2 field2...:向圖key中添加多個(gè)member,包含經(jīng)度longitude、緯度latitude 、member唯一標(biāo)識(shí)fieldgeodist key field1 field2 [m,km]:返回兩個(gè)member之間的距離geohash key field1:將指定member的坐標(biāo)轉(zhuǎn)為hash字符串形式并返回geopos key field1:返回指定member的坐標(biāo)geoseartch key FROMLONLAT longitude1 latitude1 [BYRADIUS 10km] [ASC/DESC] [WITHDIST]:給定圓心和半徑,按照升序或降序返回指定范圍內(nèi)的member,并返回距離具體值WITHDISTgeosearchstore:同geoseratch,并將結(jié)果存儲(chǔ)到指定的key中
GEO底層是用sortedSet實(shí)現(xiàn),其中經(jīng)緯度會(huì)被換算為score字段(score=a+b的意思),member唯一標(biāo)識(shí)作為value字段。

二、redis實(shí)現(xiàn)查詢附近商鋪功能
1.按照商鋪類型導(dǎo)入商鋪信息
@Resource
StringRedisTemplate stringRedisTemplate;
@Resource
IShopService shopService;
@Test
public void testLoadShopData(){
List<Shop> shops = shopService.query().list();
for (Shop shop : shops) {
stringRedisTemplate.opsForGeo().add(
"geo:shop:"+shop.getTypeId(),
new RedisGeoCommands.GeoLocation<>(
shop.getId().toString(),
new Point(shop.getX().doubleValue(),shop.getY().doubleValue())));
}
2.根據(jù)商鋪類型和距離查詢附近商鋪
@Override
public Result queryShopByType(Integer typeId, Integer current, Double x, Double y) {
if (x==null || y==null){
// 根據(jù)類型分頁查詢
Page<Shop> page = query()
.eq("type_id", typeId)
.page(new Page<>(current, 5));
// 返回?cái)?shù)據(jù)
return Result.ok(page.getRecords());
}
// 該頁起始和終止元素
int from = (current-1)*5;
int end = from + 5;
// 查詢距離內(nèi)的店鋪
GeoResults<RedisGeoCommands.GeoLocation<String>> radius = stringRedisTemplate.opsForGeo().radius(
"geo:shop:" + typeId,
new Circle(new Point(x, y), new Distance(5000)),
RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance());//指定圓心半徑m查相關(guān)店鋪,并返回店鋪距離圓心的距離
// 判空
if (radius==null){
return Result.ok(Collections.emptyList());
}
// 這里看類的結(jié)構(gòu)只能getContent
List<GeoResult<RedisGeoCommands.GeoLocation<String>>> results = radius.getContent();
// 判該頁是否有元素
if (results.size()<=from){
return Result.ok(Collections.emptyList());
}
// 截取from~end部分實(shí)現(xiàn)分頁
List<GeoResult<RedisGeoCommands.GeoLocation<String>>> results1 = results.subList(from, Math.min(end, results.size()-1));
ArrayList<Long> shopIds = new ArrayList<>();
HashMap<Long, Distance> longDistanceHashMap = new HashMap<>();
results1.forEach(r ->{
String shopId = r.getContent().getName();
shopIds.add(Long.valueOf(shopId));
Distance distance = r.getDistance();
longDistanceHashMap.put(Long.valueOf(shopId), distance);
});
List<Shop> shops = listByIds(shopIds);
for (Shop s : shops) {
double value = longDistanceHashMap.get(s.getId()).getValue();
s.setDistance(value);
}
return Result.ok(shops);
}
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Redis拓展之定時(shí)消息通知實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了Redis拓展之定時(shí)消息通知實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
redis數(shù)據(jù)結(jié)構(gòu)之String詳解
Redis以String為基礎(chǔ)類型,因C字符串效率低、非二進(jìn)制安全等問題,采用SDS動(dòng)態(tài)字符串實(shí)現(xiàn)高效存儲(chǔ),通過RedisObject封裝,支持多種編碼方式(如RAW、EMBSTR、INT)和內(nèi)存優(yōu)化策略,靈活管理數(shù)據(jù)結(jié)構(gòu)與內(nèi)存使用2025-08-08
Linux服務(wù)器安裝redis數(shù)據(jù)庫圖文教程
Redis是一個(gè)開源的使用ANSI C語言編寫、遵守BSD協(xié)議、支持網(wǎng)絡(luò)、可基于內(nèi)存亦可持久化的日志型、Key-Value數(shù)據(jù)庫,并提供多種語言的API。這篇文章主要介紹了Linux服務(wù)器安裝redis數(shù)據(jù)庫圖文教程,需要的朋友可以參考下2018-03-03
Redis調(diào)用Lua腳本及使用場(chǎng)景快速掌握
Redis?是一種非常流行的內(nèi)存數(shù)據(jù)庫,常用于數(shù)據(jù)緩存與高頻數(shù)據(jù)存儲(chǔ)。大多數(shù)開發(fā)人員可能聽說過redis可以運(yùn)行?Lua?腳本,但是可能不知道redis在什么情況下需要使用到Lua腳本2022-03-03
Redis fork進(jìn)程分配不到內(nèi)存解決方案
這篇文章主要介紹了Redis fork進(jìn)程分配不到內(nèi)存解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11
手把手教你使用redis實(shí)現(xiàn)排行榜功能
使用Redis中有序集合的特性來實(shí)現(xiàn)排行榜是又好又快的選擇,一般排行榜都是有實(shí)效性的,比如“用戶積分榜”,下面這篇文章主要給大家介紹了關(guān)于使用redis實(shí)現(xiàn)排行榜功能的相關(guān)資料,需要的朋友可以參考下2023-04-04
redis主從復(fù)制的原理及實(shí)現(xiàn)
Redis主從復(fù)制是一種數(shù)據(jù)同步機(jī)制,它通過將一個(gè)Redis實(shí)例的數(shù)據(jù)復(fù)制到其他Redis,本文主要介紹了redis主從復(fù)制的原理及實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08

