Redis中关于Key的模糊查找

4,924 阅读3分钟

可以通过Redis中keys命令进行获取key值,具体命令格式:keys pattern

文中提到redis中允许模糊查询的有3个通配符,分别是:*,?,[]

其中:

*:通配任意多个字符

?:通配单个字符

[]:通配括号内的某一个字符

=========================================================================

在实际项目中有可能会使用spring集成redis的RedisTemplate进行操作,这样在注入模板时可能会出现模糊查询不好用的情况,是因为keys方法是存在于StringRedisTemplate子类中(父类-RedisTemplate)的

在spring配置时,一定要注意!!!

=========================================================================

实际操作中具体的思路:

1. 将要查询的条件当做key进行ZSet存储

2. 在获取时,调用StringRedisTemplate.keys(pattern),例:

publicSet keys(String pattern){  
returnstringRedisTemplate.keys("*"+ pattern + "*");  
 // return stringRedisTemplate.keys("?" + pattern);  
// return stringRedisTemplate.keys("[" + pattern + "]");
}

ps:模糊查找适用于 String数据结构,对redis支持的其他结构(List、set等),没有 验证是否支持.

实践代码:

/** * redis缓存操作类 
*/@ServicepublicclassRedisCacheServiceimplementsInitializingBean{privateValueOperations valueOperations;@AutowiredprivateStringRedisTemplate redisTemplate;@SuppressWarnings("unchecked")@OverridepublicvoidafterPropertiesSet()throwsException{RedisSerializer redisSerializer =newStringRedisSerializer();		
valueOperations = redisTemplate.opsForValue();	}
/**	 * 从缓存中获取资源信息*@paramkey*@return	
 */publicListgetCacheResource(String key){		
Set<String> keys = redisTemplate.keys(key);if(CollectionUtils.isEmpty(keys)) 
{returnnewArrayList<>();		
}
List resourceCacheBOList =newArrayList<>();for(String accurateKey : keys) {			
String cacheValue = valueOperations.get(accurateKey);			
List<ResourceCacheBO> sub = JSONArray.parseArray(cacheValue,
 ResourceCacheBO.class);			
resourceCacheBOList.addAll(sub);		
}returnresourceCacheBOList;	}

【key存在,而redisTemplate查找不到】

遇到问题:存在key:“A_091_JPFX”,但是用 模糊key:“A_*_JPFX”匹配时,却匹配不到;有资料说是编码问题,按下面方式解决:

在使用redisTemplate.keys查找keys时,发现明明相应的key是存在的,模糊查询就是查找不出来;原因有二:

1.确定你的查询字符串是否正确

2.就是的你key值有可能是乱码了就是遇到\xca\xed加上你key之类的乱码!例如:这里写图片描述

你需要重新定义key

@BeanpublicRedisTemplateredisTemplate(RedisConnectionFactory factory){RedisTemplate redisTemplate =newRedisTemplate(); redisTemplate.setConnectionFactory(factory);

//key序列化方式;(不然会出现乱码;),但是如果方法上有Long等非String类型的话,会报类型转换错误;

//所以在没有自己定义key生成策略的时候,以下这个代码建议不要这么写,可以不配置或者自己实现ObjectRedisSerializer

//或者JdkSerializationRedisSerializer序列化方式;

RedisSerializer redisSerializer =newStringRedisSerializer();//Long类型不可以会出现异常信息; redisTemplate.setKeySerializer(redisSerializer); redisTemplate.setHashKeySerializer(redisSerializer); returnredisTemplate; }

完整代码:packagecn.xxt.word.analysis.service;importcn.xxt.ssm.commons.exception.BizException;importcn.xxt.ssm.commons.json.JacksonJsonUtil;importcn.xxt.word.analysis.pojo.bo.QuestCacheBO;importcn.xxt.word.analysis.pojo.bo.ResourceCacheBO;importcom.alibaba.fastjson.JSONArray;importorg.springframework.beans.factory.InitializingBean;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.redis.core.StringRedisTemplate;importorg.springframework.data.redis.core.ValueOperations;importorg.springframework.data.redis.serializer.RedisSerializer;importorg.springframework.data.redis.serializer.StringRedisSerializer;importorg.springframework.stereotype.Service;importorg.springframework.util.CollectionUtils;importorg.springframework.util.StringUtils;importjava.util.ArrayList;importjava.util.Collections;importjava.util.List;importjava.util.Set;/** * redis缓存操作类 */@ServicepublicclassRedisCacheServiceimplementsInitializingBean{privateValueOperations valueOperations;@AutowiredprivateStringRedisTemplate redisTemplate;@SuppressWarnings("unchecked")@OverridepublicvoidafterPropertiesSet()throwsException{RedisSerializer redisSerializer =newStringRedisSerializer();//Long类型不可以会出现异常信息; redisTemplate.setKeySerializer(redisSerializer); redisTemplate.setHashKeySerializer(redisSerializer); valueOperations = redisTemplate.opsForValue(); }/** * 缓存资源*@paramkey*@paramresourceCacheBOList */publicvoidcacheResource(String key, List<ResourceCacheBO> resourceCacheBOList){// 参数校验if(CollectionUtils.isEmpty(resourceCacheBOList)) {thrownewBizException(1,"参数有误"); }// 缓存 String resourceCacheValue = JacksonJsonUtil.objectToString(resourceCacheBOList); valueOperations.set(key, resourceCacheValue); }/** * 从缓存中获取资源信息*@paramkey*@return */// TODO 待测试publicListgetCacheResource(String key){ Set<String> keys = redisTemplate.keys(key);if(CollectionUtils.isEmpty(keys)) {returnnewArrayList<>(); }List resourceCacheBOList =newArrayList<>();for(String accurateKey : keys) { String cacheValue = valueOperations.get(accurateKey); List<ResourceCacheBO> sub = JSONArray.parseArray(cacheValue, ResourceCacheBO.class); resourceCacheBOList.addAll(sub); }returnresourceCacheBOList; }/** * 缓存 关键字的编码*@paramkey*@return */publicvoidcacheKeyWordCode(String key, String code){// 参数校验if(StringUtils.isEmpty(key) || StringUtils.isEmpty(code)) {thrownewBizException(1,"参数有误"); }// 缓存 valueOperations.set(key, code); }/** * 获取 关键字的编码*@paramkey*@return */publicStringgetKeyWordCode(String key){ String keyWordCode = valueOperations.get(key);if(StringUtils.isEmpty(keyWordCode)) {returnnull;}else{returnkeyWordCode; } }/** * 批量获取 关键字的编码*@paramkeys*@return */publicListbatchGetKeyWordCode(List<String> keys){ List<String> codes = valueOperations.multiGet(keys);if(CollectionUtils.isEmpty(codes)) {returnnewArrayList<>();}else{codes.removeAll(Collections.singleton(null));returncodes; } }

总结:

当你的redis数据库里面本来存的是字符串数据或者你要存取的数据就是字符串类型数据的时候,那么你就使用StringRedisTemplate即可,

但是如果你的数据是复杂的对象类型,而取出的时候又不想做任何的数据转换,直接从Redis里面取出一个对象,那么使用RedisTemplate是更好的选择。