redis(jedis)相关API ,实现与关系型数据库相似的功能

    本文简单介绍了在使用jedis操作redis这个nosql数据库过程中,总结的一些问题,例如使用jedis实现形如关系型数据库的数据关联关系处理。

    分三个层面:

        1:单表数据处理,新增一行数据到数据库中,如果存在主键id是自增情况的条件下,如何新增数据集合到数据库行数据;

        2:一对多关联关系,本文举例形如---学生&&成绩; 一个学生包含多个学科的成绩,某一个学科的的成绩属于某个学生;

        3:多对多关联关系,本文举例例如---文章&&标签; 一篇文章可以添加多个标签,某一个标签可以被包含于多个文章中;

        整体代码链接已经上传git,可以在git上查看: 

http://git.oschina.net/alexgaoyh/MutiModule-parent/blob/master/MutiModule-service/src/test/java/com/alexgaoyh/MutiModule/service/unJunit/redis/test2/TestCase.java

    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);
              }

       }



其中需要注意 sortingParameters.get("#");

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();
	}



郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。