redis模糊查找

 

 

【redis模糊查找】

原文链接:https://www.cnblogs.com/commissar-Xia/p/7759484.html

最近使用Redis优化项目功能,其中有一部分为模糊查询,找了很多帖子,也没有找到很好的解决方案和思路,最终皇天不负有心人啊,终于让我找到了!!!

感谢该帖作者:WalkerAlone  原文链接:http://blog.csdn.net/qq_28893679/article/details/53005057

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

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

其中:

*:通配任意多个字符

?:通配单个字符

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

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

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

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

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

实际操作中具体的思路:

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

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

1

2

3

4

5

public Set keys(String pattern){

  return stringRedisTemplate.keys("*" + pattern + "*");

   // return stringRedisTemplate.keys("?" + pattern);

  // return stringRedisTemplate.keys("[" + pattern + "]");

}

 

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

 

实践代码:

/**
 * redis缓存操作类
 */
@Service
public class RedisCacheService implements InitializingBean {

	private ValueOperations<String, String> valueOperations;

	@Autowired
	private StringRedisTemplate redisTemplate;

	@SuppressWarnings("unchecked")
	@Override
	public void afterPropertiesSet() throws Exception {
		RedisSerializer<String> redisSerializer = new StringRedisSerializer();
		valueOperations = redisTemplate.opsForValue();
	}

	/**
	 * 从缓存中获取资源信息
	 * @param key
	 * @return
	 */
	public List<ResourceCacheBO> getCacheResource(String key) {
		Set<String> keys = redisTemplate.keys(key);
		if (CollectionUtils.isEmpty(keys)) {
			return new ArrayList<>();
		}

		List<ResourceCacheBO> resourceCacheBOList = new ArrayList<>();
		for (String accurateKey : keys) {
			String cacheValue = valueOperations.get(accurateKey);
			List<ResourceCacheBO> sub = JSONArray.parseArray(cacheValue, ResourceCacheBO.class);
			resourceCacheBOList.addAll(sub);
		}

		return resourceCacheBOList;
	}

 

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

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

原文链接:redisTemplate.keys(pattern)模糊查询找不到keys:https://blog.csdn.net/cutterwolf/article/details/77990112

 

在使用redisTemplate.keys查找keys时,发现明明相应的key是存在的,模糊查询就是查找不出来;原因有二: 
1.确定你的查询字符串是否正确 
2.就是的你key值有可能是乱码了就是遇到\xca\xed加上你key之类的乱码!例如:这里写图片描述 
你需要重新定义key

 @Bean  
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {  
       RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();  
       redisTemplate.setConnectionFactory(factory);  

       //key序列化方式;(不然会出现乱码;),但是如果方法上有Long等非String类型的话,会报类型转换错误;  
       //所以在没有自己定义key生成策略的时候,以下这个代码建议不要这么写,可以不配置或者自己实现ObjectRedisSerializer  
       //或者JdkSerializationRedisSerializer序列化方式;  
     RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息;  
     redisTemplate.setKeySerializer(redisSerializer);  
     redisTemplate.setHashKeySerializer(redisSerializer);  

       return redisTemplate;  
    }   

 

 

完整代码:

package cn.xxt.word.analysis.service;

import cn.xxt.ssm.commons.exception.BizException;
import cn.xxt.ssm.commons.json.JacksonJsonUtil;
import cn.xxt.word.analysis.pojo.bo.QuestCacheBO;
import cn.xxt.word.analysis.pojo.bo.ResourceCacheBO;
import com.alibaba.fastjson.JSONArray;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * redis缓存操作类
 */
@Service
public class RedisCacheService implements InitializingBean {

	private ValueOperations<String, String> valueOperations;

	@Autowired
	private StringRedisTemplate redisTemplate;

	@SuppressWarnings("unchecked")
	@Override
	public void afterPropertiesSet() throws Exception {
		RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息;
		redisTemplate.setKeySerializer(redisSerializer);
		redisTemplate.setHashKeySerializer(redisSerializer);
		valueOperations = redisTemplate.opsForValue();
	}

	/**
	 * 缓存资源
	 * @param key
	 * @param resourceCacheBOList
	 */
	public void cacheResource(String key, List<ResourceCacheBO> resourceCacheBOList) {
		// 参数校验
		if (CollectionUtils.isEmpty(resourceCacheBOList)) {
			throw new BizException(1, "参数有误");
		}
		// 缓存
		String resourceCacheValue = JacksonJsonUtil.objectToString(resourceCacheBOList);
		valueOperations.set(key, resourceCacheValue);
	}

	/**
	 * 从缓存中获取资源信息
	 * @param key
	 * @return
	 */
	// TODO 待测试
	public List<ResourceCacheBO> getCacheResource(String key) {
		Set<String> keys = redisTemplate.keys(key);
		if (CollectionUtils.isEmpty(keys)) {
			return new ArrayList<>();
		}

		List<ResourceCacheBO> resourceCacheBOList = new ArrayList<>();
		for (String accurateKey : keys) {
			String cacheValue = valueOperations.get(accurateKey);
			List<ResourceCacheBO> sub = JSONArray.parseArray(cacheValue, ResourceCacheBO.class);
			resourceCacheBOList.addAll(sub);
		}

		return resourceCacheBOList;
	}

	/**
	 * 缓存 关键字的编码
	 * @param key
	 * @return
	 */
	public void cacheKeyWordCode(String key, String code) {
		// 参数校验
		if (StringUtils.isEmpty(key) || StringUtils.isEmpty(code)) {
			throw new BizException(1, "参数有误");
		}
		// 缓存
		valueOperations.set(key, code);
	}

	/**
	 * 获取 关键字的编码
	 * @param key
	 * @return
	 */
	public String getKeyWordCode(String key) {
		String keyWordCode = valueOperations.get(key);
		if (StringUtils.isEmpty(keyWordCode)) {
			return null;
		} else {
			return keyWordCode;
		}
	}

	/**
	 * 批量获取 关键字的编码
	 * @param keys
	 * @return
	 */
	public List<String> batchGetKeyWordCode(List<String> keys) {
		List<String> codes = valueOperations.multiGet(keys);
		if (CollectionUtils.isEmpty(codes)) {
			return new ArrayList<>();
		} else {
			codes.removeAll(Collections.singleton(null));
			return codes;
		}
	}

}

 

【RedisTemplate和StringRedisTemplate的区别】

原文链接:https://blog.csdn.net/notsaltedfish/article/details/75948281

 

最近在开始在学习Redis以及如何在Java当中去使用Redis,Redis是什么我这里就不说了。

我主要想说的是Redis和Java当中Spring结合起来的时候,使用到的RedisTemplate和StringRedisTemplate

他们两者之间的区别,以及该怎么使用。

RedisTemplate看这个类的名字后缀是Template,如果了解过Spring如何连接关系型数据库的,大概不会难猜出这个类是做什么的 ,它跟JdbcTemplate一样封装了对Redis的一些常用的操作,当然StringRedisTemplate跟RedisTemplate功能类似那么肯定就会有人问,为什么会需要两个Template呢,一个不就够了吗?其实他们两者之间的区别主要在于他们使用的序列化类。

  • RedisTemplate使用的是 JdkSerializationRedisSerializer
  • StringRedisTemplate使用的是 StringRedisSerializer

 

RedisTemplate使用的序列类在在操作数据的时候,比如说存入数据会将数据先序列化成字节数组

然后在存入Redis数据库,这个时候打开Redis查看的时候,你会看到你的数据不是以可读的形式

展现的,而是以字节数组显示,类似下面


当然从Redis获取数据的时候也会默认将数据当做字节数组转化,这样就会导致一个问题,当需要获取的

数据不是以字节数组存在redis当中而是正常的可读的字符串的时候,比如说下面这种形式的数据

注:使用的软件是RedisDesktopManager

RedisTemplate就无法获取导数据,这个时候获取到的值就是NULL。这个时候StringRedisTempate就派上了用场

 

当Redis当中的数据值是以可读的形式显示出来的时候,只能使用StringRedisTemplate才能获取到里面的数据。

所以当你使用RedisTemplate获取不到数据的时候请检查一下是不是Redis里面的数据是可读形式而非字节数组

 

另外我在测试的时候即使把StringRedisTemplate的序列化类修改成RedisTemplate的JdkSerializationRedisSerializer

最后还是无法获取被序列化的对象数据,即使是没有转化为对象的字节数组,代码如下

@Test

public void testRedisSerializer(){

User u = new User();

u.setName("java");

u.setSex("male");

redisTemplate.opsForHash().put("user:","1",u);

/*查看redisTemplate 的Serializer*/

System.out.println(redisTemplate.getKeySerializer());

System.out.println(redisTemplate.getValueSerializer());


/*查看StringRedisTemplate 的Serializer*/

System.out.println(stringRedisTemplate.getValueSerializer());

System.out.println(stringRedisTemplate.getValueSerializer());


/*将stringRedisTemplate序列化类设置成RedisTemplate的序列化类*/

stringRedisTemplate.setKeySerializer(new JdkSerializationRedisSerializer());

stringRedisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());


/*即使在更换stringRedisTemplate的的Serializer和redisTemplate一致的

* JdkSerializationRedisSerializer

* 最后还是无法从redis中获取序列化的数据

* */

System.out.println(stringRedisTemplate.getValueSerializer());

System.out.println(stringRedisTemplate.getValueSerializer());


User user = (User) redisTemplate.opsForHash().get("user:","1");

User user2 = (User) stringRedisTemplate.opsForHash().get("user:","1");

System.out.println("dsd");

}

总结:

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

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

 

 

  • 7
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Redis支持模糊查询,可以通过使用通配符来匹配一定范围内的key。 以下是几个常用的通配符: - *:匹配任意数量的字符,包括0个字符 - ?:匹配单个字符 使用通配符进行模糊查询的语法为: ``` KEYS pattern ``` 其中,pattern为匹配模式,可以包含通配符。 例如,要查找所有以foo开头的key,可以使用以下命令: ``` KEYS foo* ``` 要查找所有以bar结尾的key,可以使用以下命令: ``` KEYS *bar ``` 需要注意的是,使用模糊查询会影响Redis的性能,因此应该尽量避免在生产环境中使用。 ### 回答2: Redis是一种高性能的内存数据库,主要用于缓存数据和提供快速的读写操作。在Redis中,可以使用模糊查询来查找符合特定模式的键值对。 在Redis中,模糊查询主要使用通配符来匹配键的模式。通配符有两种常用的形式: 1. "*"通配符:表示匹配任意数量的字符,包括零个字符。例如,使用"key*"可以匹配以"key"开头的所有键,如"key1"、"key2"等。 2. "?"通配符:表示匹配一个字符。例如,使用"key?"可以匹配以"key"开头并且只有一个字符的键,如"key1"、"key2"等。 除了通配符,Redis还提供了一些特殊的模式匹配规则: 1. "[abc]":表示匹配括号内的任意一个字符。例如,使用"key[12]"可以匹配"key1"和"key2"。 2. "[^abc]":表示匹配不在括号内的任意一个字符。例如,使用"key[^12]"可以匹配除了"key1"和"key2"之外的键。 3. "[a-z]":表示匹配从a到z之间的任意一个字符。 使用Redis模糊查询可以很方便地查找符合特定模式的键值对,并且可以通过设置过期时间来实现缓存功能。但是需要注意的是,由于模糊查询需要遍历所有的键值对,所以在大规模数据的情况下,会影响查询的性能,建议做好优化措施。 ### 回答3: Redis模糊查询是指在使用Redis数据库进行查询时,可以使用通配符或正则表达式来匹配模式,从而进行模糊查询。 在Redis中,可以使用通配符进行模糊查询。通配符包括"*"和"?",其中"*"表示任意数量的字符,"?"表示一个字符。通过使用通配符,可以匹配的范围更加广泛,从而实现模糊查询。 另外,Redis还支持使用正则表达式进行模糊查询。正则表达式有更强的灵活性,能够更精确地匹配需要查询的数据。通过使用正则表达式,可以实现更复杂的模糊查询操作。 为了使用Redis模糊查询功能,需要使用相关的命令和参数。例如,使用KEYS命令可以获取匹配某个模式的所有键值对。使用SCAN命令可以遍历所有键值对,并根据正则表达式匹配进行过滤。 需要注意的是,在使用Redis进行模糊查询时,由于Redis是单线程的,大规模的模糊查询可能会对性能产生影响。因此,在进行模糊查询的时候,需要根据具体情况选择合适的查询方式,并注意性能优化。 总结来说,Redis模糊查询是一种通过使用通配符或正则表达式来匹配模式的查询方式,能够更灵活地查询需要的数据。在实际使用中,可以结合具体需求选择合适的查询方式,并注意性能优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值