这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战
一、实战
使用 jedis,测试环境:
pom.xml配置- 测试代码
pom.xml
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.5.2</version>
</dependency>
- 测试代码
public class JedisTest {
private Jedis jedis;
@Before
public void setUp() {
jedis = new Jedis("127.0.0.1", 6379);
}
@After
public void after() {
jedis.close();
}
@Test
public void testCache() {
// 最简单的设置缓存
jedis.set("key1", "value1");
System.out.println(jedis.get("key1"));
}
}
(14)为商品搜索构建反向索引
实战操作如下:
sadd:给商品添加一个关键词索引集合srem:删除商品smembers:获取一个商品所有的关键词sintern:对多个集合进行交集
实现如下:
public class JedisTest {
/**
* 添加商品的时候附带一些关键词
* @param productId 商品Id
* @param keywords 关键词
*/
private void addProduct(long productId, String[] keywords) {
for(String keyword : keywords) {
jedis.sadd("keyword::" + keyword + "::products", String.valueOf(productId));
}
}
/**
* 根据多个关键词搜索商品
* @param keywords 关键词
* @return 商品
*/
private Set<String> searchProduct(String[] keywords) {
List<String> keywordSetKeys = new ArrayList<String>();
for(String keyword : keywords) {
keywordSetKeys.add("keyword::" + keyword + "::products");
}
String[] keywordArray = keywordSetKeys.toArray(new String[keywordSetKeys.size()]);
return jedis.sinter(keywordArray);
}
@Test
public void testProductSearch() {
// 添加一批商品
addProduct(11, new String[]{"手机", "iphone", "潮流"});
addProduct(12, new String[]{"iphone", "潮流", "炫酷"});
addProduct(13, new String[]{"iphone", "天蓝色"});
// 根据关键词搜索商品
Set<String> searchResult = searchProduct(new String[]{"iphone", "潮流"});
System.out.println("商品搜索结果为:" + searchResult);
}
}
输出结果:
商品搜索结果为:[11, 12]
(15)实现音乐网站的排行榜程序
需求:按分数排序
主要使用数据结构:
sorted set,不能有重复的数据,且排序。
实战操作如下:
zadd:把音乐加入排行榜中,刚开始分数可能就是0zscore:可以获取音乐的分数zrem:可以删除某个音乐zincrby:可以给某个音乐增加分数zrevrank:获取音乐在排行榜里的排名,zrevrange set 0 100 withscores可以获取排名前100的热门歌曲
实现如下:
public class JedisTest {
/**
* 把新的音乐加入到排行榜里去
* @param songId 音乐
*/
private void addSong(long songId) {
jedis.zadd("music_ranking_list", 0, String.valueOf(songId));
}
/**
* 增加歌曲的分数
* @param songId 音乐
* @param score 分数
*/
private void incrementSongScore(long songId, double score) {
jedis.zincrby("music_ranking_list", score, String.valueOf(songId));
}
/**
* 获取歌曲在排行榜里的排名
* @param songId 音乐
* @return 排名
*/
private long getSongRank(long songId) {
return jedis.zrevrank("music_ranking_list", String.valueOf(songId));
}
/**
* 获取音乐排行榜
* @return 排行榜
*/
private Set<Tuple> getMusicRankingList() {
return jedis.zrevrangeWithScores("music_ranking_list", 0, 2);
}
@Test
public void testMusicRank() {
for(int i = 0; i < 20; i++) {
addSong(i + 1);
}
incrementSongScore(5, 3.2);
incrementSongScore(15, 5.6);
incrementSongScore(7, 9.6);
long songRank = getSongRank(5);
System.out.println("查看id为5的歌曲的排名:" + (songRank + 1));
Set<Tuple> musicRankingList = getMusicRankingList();
System.out.println("查看音乐排行榜排名前3个的歌曲:" + musicRankingList);
}
}
输出结果:
查看id为5的歌曲的排名:3
查看音乐排行榜排名前3个的歌曲:[[7,9.6], [15,5.6], [5,3.2]]
(16)实现一个新闻推荐机制
主要使用数据结构:
sorted set,不能有重复的数据,且排序。
实战操作如下:
zadd:把当日最新的新闻加入到一个集合里zcard:统计当日最新新闻zcount:可以获取指定分数范围的数量zrevrangebyscore max_time min_time start_index count withscores:按照时间分数进行倒序排序,然后获取指定的分页
实现如下:
public class JedisTest {
/**
* 加入一篇新闻
* @param newsId 新闻Id
*/
private void addNews(long newsId, long timestamp) {
jedis.zadd("news", timestamp, String.valueOf(newsId));
}
/**
* 搜索新闻
* @param maxTimestamp 最大时间
* @param minTimestamp 最小时间
* @param index 索引
* @param count 总数
* @return 新闻
*/
private Set<Tuple> searchNews(long maxTimestamp, long minTimestamp, int index, int count) {
return jedis.zrevrangeByScoreWithScores("news", maxTimestamp, minTimestamp, index, count);
}
@Test
public void testNews() {
for(int i = 0; i < 20; i++) {
addNews(i + 1, i + 1);
}
long maxTimestamp = 18;
long minTimestamp = 2;
int pageNo = 1;
int pageSize = 10;
int startIndex = (pageNo - 1) * 10;
Set<Tuple> searchResult = searchNews(
maxTimestamp, minTimestamp, startIndex, pageSize);
System.out.println("搜索指定时间范围内的新闻的第一页:" + searchResult);
}
}
输出结果:
搜索指定时间范围内的新闻的第一页:[[18,18.0], [17,17.0], [16,16.0], [15,15.0], [14,14.0], [13,13.0], [12,12.0], [11,11.0], [10,10.0], [9,9.0]]
(17)购买此商品的顾客也同时购买
主要使用数据结构:
sorted set,不能有重复的数据,且排序。
实战操作如下:
zremrangebyscore:按照范围查询zincrby:递增
实现如下:
public class JedisTest {
/**
* 继续购买商品
* @param productId 商品Id
* @param otherProductId 其他商品Id
*/
private void continuePurchase(long productId, long otherProductId) {
jedis.zincrby("continue_purchase_products::" + productId, 1, String.valueOf(otherProductId));
}
/**
* 推荐其他人购买过的其他商品
* @param productId 商品Id
* @return 商品
*/
private Set<Tuple> getRecommendProducts(long productId) {
return jedis.zrevrangeWithScores("continue_purchase_products::" + productId, 0, 2);
}
@Test
public void testProductRecommend() {
int productId = 1;
for(int i = 0; i < 20; i++) {
continuePurchase(productId, i + 2);
}
for(int i = 0; i < 3; i++) {
continuePurchase(productId, i + 2);
}
Set<Tuple> recommendProducts = getRecommendProducts(productId);
System.out.println("推荐其他人购买过的商品:" + recommendProducts);
}
}
输出结果:
推荐其他人购买过的商品:[[4,2.0], [3,2.0], [2,2.0]]
(18)网站搜索框的自动补全功能
需求:
对于输入的每个搜索词,都会遍历一下,拼接出来,然后
zincrby auto_complete::潜在搜索词 权重 完整搜索词,这样的话,就是每个潜在搜索词都会有一个集合,集合里是各种可能对应的搜索词和权重分数
查询:zrevrange set 0 9,潜在搜索词按照权重分数倒序拿出最近的10个搜索词,做一个自动提示和补全
实现如下:
public class JedisTest {
/**
* 搜索某个关键词
* @param keyword 关键词
*/
private void search(String keyword) {
char[] keywordCharArray = keyword.toCharArray();
StringBuffer potentialKeyword = new StringBuffer("");
for(char keywordChar : keywordCharArray) {
potentialKeyword.append(keywordChar);
jedis.zincrby(
"potential_Keyword::" + potentialKeyword.toString() + "::keywords",
new Date().getTime(),
keyword);
}
}
/**
* 获取自动补全列表
* @param potentialKeyword 潜在补全列表
* @return 列表
*/
private Set<String> getAutoCompleteList(String potentialKeyword) {
return jedis.zrevrange("potential_Keyword::" + potentialKeyword + "::keywords",
0, 2);
}
@Test
public void testAutoComplete() {
search("我爱大家");
search("我喜欢学习Redis");
search("我很喜欢一个城市");
search("我不太喜欢玩儿");
search("我喜欢学习Spark");
Set<String> autoCompleteList = getAutoCompleteList("我");
System.out.println("第一次自动补全推荐:" + autoCompleteList);
autoCompleteList = getAutoCompleteList("我喜");
System.out.println("第二次自动补全推荐:" + autoCompleteList);
}
}
输出结果:
第一次自动补全推荐:[我喜欢学习Spark, 我很喜欢一个城市, 我不太喜欢玩儿]
第二次自动补全推荐:[我喜欢学习Spark, 我喜欢学习Redis]