Redis 中的集合最多存储 232 - 1 个元素,具备固有集合的性质(唯一性、无序性),Redis 中的集合是通过 Hash Table 数据结构实现的,增删查的时间复杂度都是 $O(1)$,其中最方便的一点还是支持集合间的运算。
Redis 的集合数据类型都不支持嵌套,集合里面不能存储集合类型数据,集合里面不能存储集合而只能存储字符串。
@Test public void basicOperationOnSet() { long effected = j.sadd("numbers", "1", "2", "3"); assertEquals(3L, effected); effected = j.sadd("numbers", "3", "4", "5"); assertEquals(2L, effected); effected = j.srem("numbers", "1", "2"); assertEquals(2L, effected); boolean rel = j.sismember("numbers", "1"); assertFalse(rel); rel = j.sismember("numbers", "3"); assertTrue(rel); Set<String> numbers = j.smembers("numbers"); assertEquals(3, numbers.size()); assertTrue(numbers.contains("3")); assertTrue(numbers.contains("4")); assertTrue(numbers.contains("5")); }
@Test public void setDiff() { // if you want to store the result into other key, just append "store" behind the command long effected = j.sadd("setA", "1", "2", "3"); assertEquals(3L, effected); effected = j.sadd("setB", "3", "4", "5"); assertEquals(3L, effected); effected = j.sadd("setC", "2", "5", "6"); assertEquals(3L, effected); // A - B Set<String> diffs = j.sdiff("setA", "setB"); assertEquals(2, diffs.size()); assertTrue(diffs.contains("1")); assertTrue(diffs.contains("2")); // A - B - C diffs = j.sdiff("setA", "setB", "setC"); assertEquals(1, diffs.size()); assertTrue(diffs.contains("1")); }
@Test public void setInter() { // if you want to store the result into other key, just append "store" behind the command long effected = j.sadd("setA", "1", "2", "3"); assertEquals(3L, effected); effected = j.sadd("setB", "3", "4", "5"); assertEquals(3L, effected); effected = j.sadd("setC", "2", "3", "6"); assertEquals(3L, effected); Set<String> inters = j.sinter("setA", "setB", "setC"); assertEquals(1, inters.size()); assertTrue(inters.contains("3")); }
@Test public void setUnion() { // if you want to store the result into other key, just append "store" behind the command long effected = j.sadd("setA", "1", "2", "3"); assertEquals(3L, effected); effected = j.sadd("setB", "3", "4", "5"); assertEquals(3L, effected); effected = j.sadd("setC", "2", "3", "6"); assertEquals(3L, effected); Set<String> union = j.sunion("setA", "setB", "setC"); assertNotNull(union); assertEquals(6, union.size()); assertTrue(union.contains("6")); assertTrue(union.contains("5")); assertTrue(union.contains("4")); assertTrue(union.contains("3")); assertTrue(union.contains("2")); assertTrue(union.contains("1")); }
@Test public void randomGetFromSet() { long effected = j.sadd("setA", "1", "2", "3"); assertEquals(3L, effected); String value = j.srandmember("setA"); assertTrue(value.equals("1") || value.equals("2") || value.equals("3")); List<String> setA = j.srandmember("setA", 2); assertEquals(2, setA.size()); String sPop = j.spop("setA"); assertNotNull(sPop); long size = j.scard("setA"); assertEquals(2L, size); }
一篇文章的所有标签都是互不相同的,而且展示时没有顺序,所以我们可以使用集合来存储文章的标签;
同样的,有时我们希望通过文章标签来找到文章,如果通过检索所有文章的标签来捡出指定标签的文章似乎有些太低效了,因为我们也可以创建标签的 key,然后在这个 key 下面存储不同的值。最后的示意图大致是这样的:
如果想要获取对应已经发布的指定标签的文章的 ID 只需要查看 tag 标签对应的已经发布的文章集合就可以了,如果想要查看拥有多个标签的文章只需要求交集即可。