【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
|
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是更好的選擇。