标签:
本文简单介绍了在使用jedis操作redis这个nosql数据库过程中,总结的一些问题,例如使用jedis实现形如关系型数据库的数据关联关系处理。
分三个层面:
1:单表数据处理,新增一行数据到数据库中,如果存在主键id是自增情况的条件下,如何新增数据集合到数据库行数据;
2:一对多关联关系,本文举例形如---学生&&成绩; 一个学生包含多个学科的成绩,某一个学科的的成绩属于某个学生;
3:多对多关联关系,本文举例例如---文章&&标签; 一篇文章可以添加多个标签,某一个标签可以被包含于多个文章中;
整体代码链接已经上传git,可以在git上查看:
1:单表数据处理
/**
* [向Redis list压入ID而不是实际的数据]
在上面的例子里 ,我们将“对象”(此例中是简单消息)直接压入Redis list,但通常不应这么做,
由于对象可能被多次引用:例如在一个list中维护其时间顺序,在一个集合中保存它的类别,只要有必要,它还会出现在其他list中,等等。
让我们回到reddit.com的例子,将用户提交的链接(新闻)添加到list中,有更可靠的方法如下所示:
$ redis-cli incr next.news.id
(integer) 1
$ redis-cli set news:1:title "Redis is simple"
OK
$ redis-cli set news:1:url "http://code.google.com/p/redis"
OK
$ redis-cli lpush submitted.news 1
OK
我们自增一个key,很容易得到一个独一无二的自增ID,然后通过此ID创建对象–为对象的每个字段设置一个key。最后将新对象的ID压入submitted.news list。
这只是牛刀小试。在命令参考文档中可以读到所有和list有关的命令。你可以删除元素,旋转list,根据索引获取和设置元素,当然也可以用LLEN得到list的长度。
*
* 形如关系型数据库的单表一行数据(主键id为自增)
* 自定义一个自增的id , jedis.incr(key),这个key可以形如mysql这种关系型数据库的自增主键id
* 形如关系型数据库的一行数据,自增主键id:jedis.incr(key) 他对应的数据内容:jedis.get("ad:adinfo:" + adInfoId + ":title") jedis.get("ad:adinfo:" + adInfoId + ":url")
* 这样,在查询这张‘表’结构下的所有数据时,可以匹配查询即可
*/
public static void testListStrUsage() {
String title = "alexgaoyh";
String url = "http://git.oschina.net/alexgaoyh";
Jedis jedis = RedisUtil.getJedis(IP, PORT);
long adInfoId = jedis.incr("ad:adinfo:next.id");
jedis.set("ad:adinfo:" + adInfoId + ":title", title);
jedis.set("ad:adinfo:" + adInfoId + ":url", url);
jedis.lpush("ad:adinfo", String.valueOf(adInfoId));
String resultTitle = jedis.get("ad:adinfo:" + adInfoId + ":title");
String resultUrl = jedis.get("ad:adinfo:" + adInfoId + ":url");
List<String> ids = jedis.lrange("ad:adinfo", 0, -1);
System.out.println(resultTitle);
System.out.println(resultUrl);
System.out.println(ids);
/**
* dbsize返回的是所有key的数目,包括已经过期的, 而redis-cli keys "*"查询得到的是有效的key数目
*/
System.out.println(jedis.dbSize());
//清空所有的key
jedis.flushAll();
}
2:一对多关联关系
/**
* sort list
* LIST结合hash的排序
* 根据指定的SortingParams排序方式,将符合条件的数据格式进行返回
* 关联关系处理,
* 可以理解为studentlist代表学生的整体数据集合
* hset方法,可以将某个学生user:id下的某个域(学科)的成绩(value)进行数据保存
* 根据匹配条件,将相对应的成绩进行输出
*/
public static void testSort2() {
Jedis jedis = RedisUtil.getJedis(IP, PORT);
jedis.del("user:66", "user:55", "user:33", "user:22", "user:11", "userlist");
jedis.lpush("studentlist", "33");
jedis.lpush("studentlist", "22");
jedis.lpush("studentlist", "55");
jedis.lpush("studentlist", "11");
//将哈希表 key 中的域 field 的值设为 value 。 如果 key 不存在,一个新的哈希表被创建并进行 HSET 操作。 如果域 field 已经存在于哈希表中,旧值将被覆盖。
jedis.hset("user:66", "math", "66");
jedis.hset("user:55", "math", "55");
jedis.hset("user:33", "math", "33");
jedis.hset("user:22", "math", "22");
jedis.hset("user:11", "math", "11");//学生user:编号,在field域(某个学科-数学/英语)上的成绩(value)
jedis.hset("user:11", "english", "110");
jedis.hset("user:22", "english", "220");
jedis.hset("user:33", "english", "330");
jedis.hset("user:55", "english", "550");
jedis.hset("user:66", "english", "660");
SortingParams sortingParameters = new SortingParams();
// 符号 "->" 用于分割哈希表的键名(key name)和索引域(hash field),格式为 "key->field" 。
sortingParameters.desc();
sortingParameters.get("user:*->math");
sortingParameters.get("user:*->english");
List<String> result = jedis.sort("studentlist", sortingParameters);
for (String item : result) {
System.out.println("item...." + item);
}
/**
* 对应的redis客户端命令是:sort ml get user*->name sort ml get user:*->name get
* user:*->add
*/
}
/**
* sort set
* SET结合String的排序
* REL关系相关处理操作 好友列表 好友信息 好友成绩数据信息添加即相应的数据输出
* 输出好友id,好友的详细信息,好友的对应成绩
*/
public static void testSort3() {
Jedis jedis = RedisUtil. getJedis( IP, PORT);
jedis.del( "tom:friend:list" , "score:uid:123" , "score:uid:456" ,
"score:uid:789" , "score:uid:101" , "uid:123" , "uid:456" ,
"uid:789" , "uid:101" );
jedis.sadd( "tom:friend:list" , "123" ); // tom的好友列表
jedis.sadd( "tom:friend:list" , "456" );
jedis.sadd( "tom:friend:list" , "789" );
jedis.sadd( "tom:friend:list" , "101" );
jedis.set( "score:uid:123" , "1000" ); // 好友对应的成绩
jedis.set( "score:uid:456" , "6000" );
jedis.set( "score:uid:789" , "100" );
jedis.set( "score:uid:101" , "5999" );
jedis.set( "uid:123" , "{‘uid‘:123,‘name‘:‘lucy‘}" ); // 好友的详细信息
jedis.set( "uid:456" , "{‘uid‘:456,‘name‘:‘jack‘}" );
jedis.set( "uid:789" , "{‘uid‘:789,‘name‘:‘jay‘}" );
jedis.set( "uid:101" , "{‘uid‘:101,‘name‘:‘jolin‘}" );
SortingParams sortingParameters = new SortingParams();
sortingParameters.desc();
// sortingParameters.limit(0, 2);
// 注意GET操作是有序的,GET user_name_* GET user_password_*
// 和 GET user_password_* GET user_name_*返回的结果位置不同
sortingParameters.get( "#" );// GET 还有一个特殊的规则—— "GET #"
// ,用于获取被排序对象(tom:friend:list)(我们这里的例子是 user_id )的当前元素。
sortingParameters.get( "uid:*" );
sortingParameters.get( "score:uid:*" );
sortingParameters.by( "score:uid:*" );
// 对应的 redis 命令是./redis -cli sort tom:friend:list by score:uid:* get # get
// uid :* get score:uid:*
List<String> result = jedis.sort( "tom:friend:list" , sortingParameters);
for (String item : result) {
System. out .println("item..." + item);
}
}
GET 还有一个特殊的规则—— "GET #" 用于获取被排序对象(tom:friend:list)(我们这里的例子是 user_id )的当前元素。
3:多对多关联关系
/**
* 下面是一个简单的方案:对每个想加标签的对象,用一个标签ID集合与之关联,并且对每个已有的标签,一组对象ID与之关联。 例如假设我们的新闻ID
* 1000被加了三个标签tag 1,2,5和77,就可以设置下面两个集合:
* $ redis-cli sadd news:1000:tags 1
* (integer) 1
* $ redis-cli sadd news:1000:tags 2
* (integer) 1
* $ redis-cli sadd news:1000:tags 5
* (integer) 1
* $ redis-cli sadd news:1000:tags 77
* (integer) 1
* $ redis-cli sadd tag:1:objects 1000
* (integer) 1
* $ redis-cli sadd tag:2:objects 1000
* (integer) 1
* $ redis-cli sadd tag:5:objects 1000
* (integer) 1
* $ redis-cli sadd tag:77:objects 1000
* (integer) 1
* 要获取一个对象的所有标签,如此简单:
* $ redis-cli smembers news:1000:tags
* 1.5 2.1 3.77 4.2
* 而有些看上去并不简单的操作仍然能使用相应的Redis命令轻松实现。
* 例如我们也许想获得一份同时拥有标签1, 2,10和27的对象列表。这可以用SINTER命令来做,他可以在不同集合之间取出交集。
* 因此为达目的我们只需: $ redis-cli sinter tag:1:objects tag:2:objects tag:10:objects tag:27:objects ... no result
* in our dataset composed of just one object ...
* 在命令参考文档中可以找到和集合相关的其他命令,令人感兴趣的一抓一大把。一定要留意SORT命令,Redis集合和list都是可排序的。
*
* 关系型数据库双向关联操作 一个文章对应多个标签,一个标签可以被多个文章关联
* 多对多的数据库表结构
*/
public static void testSetUsage() {
Jedis jedis = RedisUtil.getJedis(IP, PORT);
//某个文章包含的标签
jedis.sadd("zhongsou:news:1000:tags", "1");
jedis.sadd("zhongsou:news:1000:tags", "2");
jedis.sadd("zhongsou:news:1000:tags", "5");
jedis.sadd("zhongsou:news:1000:tags", "77");
jedis.sadd("zhongsou:news:2000:tags", "1");
jedis.sadd("zhongsou:news:2000:tags", "2");
jedis.sadd("zhongsou:news:2000:tags", "5");
jedis.sadd("zhongsou:news:2000:tags", "77");
jedis.sadd("zhongsou:news:3000:tags", "2");
jedis.sadd("zhongsou:news:4000:tags", "77");
jedis.sadd("zhongsou:news:5000:tags", "1");
jedis.sadd("zhongsou:news:6000:tags", "5");
//某个标签包含的对应的文章id
jedis.sadd("zhongsou:tag:1:objects", 1000 + "");
jedis.sadd("zhongsou:tag:2:objects", 1000 + "");
jedis.sadd("zhongsou:tag:5:objects", 1000 + "");
jedis.sadd("zhongsou:tag:77:objects", 1000 + "");
jedis.sadd("zhongsou:tag:1:objects", 2000 + "");
jedis.sadd("zhongsou:tag:2:objects", 2000 + "");
jedis.sadd("zhongsou:tag:5:objects", 2000 + "");
jedis.sadd("zhongsou:tag:77:objects", 2000 + "");
//返回一个集合的全部成员,该集合是所有给定集合的交集
//这四个标签全部都被包含的文章id集合
Set<String> sets = jedis.sinter("zhongsou:tag:1:objects",
"zhongsou:tag:2:objects", "zhongsou:tag:5:objects",
"zhongsou:tag:77:objects");
System.out.println(sets);
jedis.flushAll();
}
redis(jedis)相关API ,实现与关系型数据库相似的功能
标签:
原文地址:http://my.oschina.net/alexgaoyh/blog/424741