11 GEO数据结构的基本用法
添加坐标,底层使用zset实现
GEOADD g1 116.378248 39.865275 bjn 116.42803 39.903738 bjz 116.322287 39.893729 bjx
两个点之间距离
geodist g1 bjn bjx km
某坐标附近10km内所有火车站以及距离。
GEOSEARCH g1 fromlonlat 116.397904 39.909005 byradius 10 km withdist
12 导入数据到GEO
导入代码
@Test
void loadShopData() {
// 1.查询店铺信息
List<Shop> list = shopService.list();
// 2.把店铺分组,按照typeId分组,typeId一致的放到一个集合
Map<Long, List<Shop>> map = list.stream().collect(Collectors.groupingBy(Shop::getTypeId));
// 3.分批完成写入Redis
for (Map.Entry<Long, List<Shop>> entry : map.entrySet()) {
// 3.1.获取类型id
Long typeId = entry.getKey();
String key = SHOP_GEO_KEY + typeId;
// 3.2.获取同类型的店铺的集合
List<Shop> value = entry.getValue();
List<RedisGeoCommands.GeoLocation<String>> locations = new ArrayList<>(value.size());
// 3.3.写入redis GEOADD key 经度 纬度 member
for (Shop shop : value) {
// stringRedisTemplate.opsForGeo().add(key, new Point(shop.getX(), shop.getY()), shop.getId().toString());
locations.add(new RedisGeoCommands.GeoLocation<>(
shop.getId().toString(),
new Point(shop.getX(), shop.getY())
));
}
stringRedisTemplate.opsForGeo().add(key, locations);
}
}
结果
15 BitMap功能演示
背景
用户数量很大,数据量非常大。
程序实现签到卡功能。
把每一个bit对应当月的每一天,形成映射关系。位图。
BITFIELD 查询数组中指定位置的值,一次可以查询多个。
BITOPS 查找bit数组指定范围内第一个出现0或1的位置。
应用
获取多个比特位的结果
bitfield bm1 get u2 0
查找第一个元素出现的位置
bitpos bm1 1
16 实现签到功能
将当前用户当天签到信息保存到redis中。
代码
public Result sign() {
// 1.获取当前登录用户
Long userId = UserHolder.getUser().getId();
// 2.获取日期
LocalDateTime now = LocalDateTime.now();
// 3.拼接key
String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
String key = USER_SIGN_KEY + userId + keySuffix;
// 4.获取今天是本月的第几天
int dayOfMonth = now.getDayOfMonth();
// 5.写入Redis SETBIT key offset 1
stringRedisTemplate.opsForValue().setBit(key, dayOfMonth - 1, true);
return Result.ok();
}
测试及结果
其中使用工具后台插入一条数据
17 统计连续签到
获取本月截至今天为止的所有签到数据。
与1做与运算,得到这个数本身。
代码
public Result signCount1() {
//获取当前登录用户
Long userId = UserHolder.getUser().getId();
//获取当前日期
LocalDateTime now = LocalDateTime.now();
//拼接key
String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
String key=USER_SIGN_KEY+userId+keySuffix;
//当前是这个月的第几天
int dayOfMonth = now.getDayOfMonth();
//获取本月为止的签到记录
List<Long> result = stringRedisTemplate.opsForValue().bitField(key, BitFieldSubCommands.create()
.get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0));
if(result==null||result.isEmpty()){
//没有任何签到结果
return Result.ok(0);
}
Long num = result.get(0);
if(num==null||num==0){
return Result.ok(0);
}
//循环遍历
int count=0;
while (true){
//6.1 让这个数字和1 与运算 得到结果最后一位bit位
if((num&1)==0){
//判断是否为0
break;
}else {
count++;
}
num>>>=1;
}
return Result.ok(count);
}