当前位置:网站首页 > 数据科学与大数据 > 正文

NoSQL数据库(二)04-Redis数据类型——集合类型之介绍、命令-增加和删除元素、获得集合中的所有元素、判断元素是否在集合中、集合间运算

NoSQL数据库(二)04-Redis数据类型——集合类型之介绍、命令-增加和删除元素、获得集合中的所有元素、判断元素是否在集合中、集合间运算

集合类型

Redis 有一种数据类型很适合存储文章的标签,它就是集合类型。

介绍

集合的概念高中的数学课就学习过。在集合中的每个元素都是不同的,且没有顺序。一个集合类型(set)键可以存储至多2的32次方 −1个(相信这个数字对大家来说已经很熟悉了)字符串。 集合类型和列表类型有相似之处,但很容易将它们区分开来,

在这里插入图片描述

集合类型的常用操作是向集合中加入或删除元素、判断某个元素是否存在等,由于集合类型在Redis内部是使用值为空的散列表(hash table)实现的,所以这些操作的时间复杂度都是O(1)。最方便的是多个集合类型键之间还可以进行并集、交集和差集运算,稍后就会看到灵活运用这一特性带来的便利。

命令
  1. 增加/删除元素

    SADD key member [member …]

    SREM key member [member …]

    SADD 命令用来向集合中增加一个或多个元素,如果键不存在则会自动创建。因为在一个集合中不能有相同的元素,所以如果要加入的元素已经存在于集合中就会忽略这个元素。本命令的返回值是成功加入的元素数量(忽略的元素不计算在内)。例如:

     redis> SADD letters a (integer) 1 redis> SADD letters a b c (integer) 2 

    第二条SADD命令的返回值为2是因为元素“a”已经存在,所以实际上只加入了两个元素。

    SREM命令用来从集合中删除一个或多个元素,并返回删除成功的个数,例如:

     redis> SREM letters c d (integer) 1 

    由于元素“d”在集合中不存在,所以只删除了一个元素,返回值为1。

2.获得集合中的所有元素

SMEMBERS key

SMEMBERS命令会返回集合中的所有元素,例如:

redis> SMEMBERS letters 1) "b" 2) "a" 
  1. 判断元素是否在集合中

    SISMEMBER key member

    判断一个元素是否在集合中是一个时间复杂度为O(1)的操作,无论集合中有多少个元素,SISMEMBER命令始终可以极快地返回结果。当值存在时判断一个元素是否在集合中是一个时间复杂度为O(1)的操作,无论集合中有多少个元素,SISMEMBER命令始终可以极快地返回结果。当值存在时 SISMEMBER命令返回1,当值不存在或键不存在时返回0,例如:

    redis> SISMEMBER letters a (integer) 1 redis> SISMEMBER letters d (integer) 0 

4.集合间运算

SDIFF key [key „]

SINTER key [key „]

SUNION key [key „]

接下来要介绍的3个命令都是用来进行多个集合间运算的。

1)SDIFF命令用来对多个集合执行差集运算。集合A与集合B的差集表示为A−B,代表所有属于A且不属于B的元素构成的集合(如图3-13所示),即A−B ={x | x∈A且x∈B}。例如:

在这里插入图片描述

{1, 2, 3} - {2, 3, 4} = {1} {2, 3, 4} - {1, 2, 3} = {4} SDIFF命令的使用方法如下:

redis> SADD setA 1 2 3 (integer) 3 redis> SADD setB 2 3 4 (integer) 3 redis> SDIFF setA setB 1) "1" redis> SDIFF setB setA 1) "4" 

SDIFF命令支持同时传入多个键,例如:

redis> SADD setC 2 3 (integer) 2 redis> SDIFF setA setB setC 1) "1" 

(2)SINTER命令用来对多个集合执行交集运算。集合A与集合B的交集表示为A ∩ B,代表所有属于A 且属于B的元素构成的集合(如图3-14所示),即A ∩ B ={x | x ∈ A 且x ∈B}。

例如: {1, 2, 3} ∩ {2, 3, 4} = {2, 3} SINTER命令的使用方法如下:

redis> SINTER setA setB 1) "2" 2) "3" 

SINTER命令同样支持同时传入多个键,如:

redis> SINTER setA setB setC 1) "2" 2) "3" 

(3)SUNION命令用来对多个集合执行并集运算。集合A与集合B的并集表示为A∪B,代表所有属于A 或属于B的元素构成的集合(如图3-15所示)即A∪B ={x | x∈A或x ∈B}。

例如: {1, 2, 3} ∪{2, 3, 4} = {1, 2, 3, 4}

在这里插入图片描述

redis> SUNION setA setB 1) "1" 2) "2" 3) "3" 4) "4" 

SUNION命令同样支持同时传入多个键,例如:

redis> SUNION setA setB setC 1) "1" 2) "2" 3) "3" 4) "4" 
ex: 存储文章标签

考虑到一个文章的所有标签都是互不相同的,而且展示时对这些标签的排列顺序并没有要求,我们可以使用集合类型键存储文章标签。

对每篇文章使用键名为post:文章ID:tags的键存储该篇文章的标签。具体操作如伪代码:

var redis = require('redis'); var client = new redis({ 
    // 配置 }); client.sadd('post:42:tags 杂文 技术文章 java'); client.srem('post:42:tags 杂文'); var tags = client.smembers('post:42:tags'); 

使用集合类型键存储标签适合需要单独增加或删除标签的场合。如在 WordPress博客程序中无论是添加还是删除标签都是针对单个标签的(如图 3-16 所示),可以直观地使用SADD和SREM命令完成操作。

另一方面,有些地方需要用户直接设置所有标签后一起上传修改,图3-17所示是某网站的个人资料编辑页面,用户编辑自己的爱好后提交,程序直接覆盖原来的标签数据,整个过程没有针对单个标签的操作,并未利用到集合类型的优势,所以此时也可以直接使用字符串类型键存储标签数据。

在这里插入图片描述

之所以特意提到这个在实践中的差别是想说明对于 Redis 存储方式的选择并没有绝对的规则,比如之前介绍过使用列表类型存储访客评论,但是在一些特定的场合下散列类型甚至字符串类型可能更适合。

ex: 通过标签搜索文章

有时我们还需要列出某个标签下的所有文章,甚至需要获得同时属于某几个标签的文章列表,这种需求在传统关系数据库中实现起来比较复杂,下面举一个例子。

现有3张表,即posts、tags和posts_tags,分别存储文章数据、标签、文章与标签的对应关系。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

为了找到同时属于“Java”、“MySQL”和“Redis”这3个标签的文章,需要使用如下的SQL语句:

SELECT p.post_title FROM posts_tags pt, posts p, tags t WHERE pt.tag_id = t.tag_id AND (t.tag_name IN ('Java', 'MySQL', 'Redis')) AND p.post_id = pt.post_id GROUP BY p.post_id HAVING COUNT(p.post_id)=3; 

很明显看到这样的 SQL 语句不仅效率相对较低,而且不易阅读和维护。而使用Redis可以很简单直接地实现这一需求。

为每一个标签使用一个名为具体做法是为每个标签使用一个名为tag:标签名称:posts的集合类型键存储标有该标签的文章ID列表。假设现在有3篇文章,ID分别为1、2、3,其中ID为1的文章标签是“Java”,ID 为 2 的文章标签是“Java”、“MySQL”,ID 为 3 的文章标签是“Java”、“MySQL”和“Redis”。

在这里插入图片描述

最简单的,当需要获取标记“MySQL”标签的文章时只需要使用命令 SMEMBER Stag:MySQL:posts即可。如果要实现找到同时属于Java、MySQL和Redis 3 个标签的文章,只需要将tag:Java:posts、tag:MySQL:posts和tag:Redis:posts这3个键取交集,借助SINTER命令即可轻松完成。

命令补充
  1. 获取集合中的元素个数

SCARD key

redis> SMEMBERS letters 1) "b" 2) "a" redis> SCARD letters (integer) 2 
  1. 进行集合运算并将结果存储

    SDIFFSTORE destination key [key …]

    SINTERSTORE destination key [key …]

    SUNIONSTORE destination key [key …]

SDIFFSTORE命令和SDIFF命令功能一样,唯一的区别就是前者不会直接返回运算结果,而是将结果存储在destination键中。 SDIFFSTORE命令常用于需要进行多步集合运算的场景中,如需要先计算差集再将结果和其他键计算交集。 SINTERSTORE和SUNIONSTORE命令与之类似,不再赘述。

  1. 随机获得集合中的元素

    SRANDMEMBER key [count]

redis> SRANDMEMBER letters "a" redis> SRANDMEMBER letters "b" redis> SRANDMEMBER letters "a" 

还可以传递count参数来一次随机获得多个元素,根据count的正负不同,具体表现也不同。

(1)当count为正数时,SRANDMEMBER会随机从集合里获得count个不重复的元素。如果count的值大于集合中的元素个数,则SRANDMEMBER会返回集合中的全部元素。

(2)当count为负数时,SRANDMEMBER会随机从集合里获得|count|个的元素,这些元素有可能同。

4.从集合中弹出一个元素

SPOP key

我们学习过LPOP命令,作用是从列表左边弹出一个元素(即返回元素的值并删除它)。SPOP命令的作用与之类似,但由于集合类型的元素是无序的,所以 SPOP命令会从集合中随机选择一个元素弹出

实例

set_demo.js

var redis = require('redis'); var client = new redis({ 
    }); // 存储标签 post:id:comments post:id:tags client.sadd('post:42:tags 杂文 技术 java nodejs'); //存储 client.srem('post:42:tags 技术'); var tags = client.smember('post:42:tags'); 

emo.js

var redis = require('redis'); var client = new redis({ 
    }); // 存储标签 post:id:comments post:id:tags client.sadd('post:42:tags 杂文 技术 java nodejs'); //存储 client.srem('post:42:tags 技术'); var tags = client.smember('post:42:tags'); 
到此这篇NoSQL数据库(二)04-Redis数据类型——集合类型之介绍、命令-增加和删除元素、获得集合中的所有元素、判断元素是否在集合中、集合间运算的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • NoSQL数据库(二)06——redis总结之发展、特点、安装、操作 & 数据类型之字符串数据类型、散列、列表、集合、有序集合2024-12-01 14:09:07
  • NoSQL数据库(三)01-Redis进阶与实战——redis事务命令与错误处理、事务中的watch命令2024-12-01 14:09:07
  • NoSQL数据库(三)02-Redis进阶与实战——EXPIRE命令设置过期时间-实现定期检测删除过期数据 & EXPIRE实现和优化访问服务器频率限制2024-12-01 14:09:07
  • NoSQL数据库(三)03-Redis进阶与实战——EXPIRE实现服务器缓存数据 & sort实现排序之对列表类型、有序集合和非数字类型进行排序 & Redis的底层通信协议对管道提供支持2024-12-01 14:09:07
  • NoSQL数据库(三)04-Redis进阶与实战——nodejs操作redis数据库之ioredis更新属于node_redis改良版 & ioredis的可视化工具安装、基本语法、管道与事务2024-12-01 14:09:07
  • NoSQL数据库(二)03-Redis数据类型——列表类型之介绍、命令-向列表两端增加元素、从列表两端弹出元素、获取列表中元素的个数、删除列表中指定的值2024-12-01 14:09:07
  • NoSQL数据库(二)02-Redis数据类型——实践-散列类型命令之散列存储逻辑、获取id、修改缩略名2024-12-01 14:09:07
  • NoSQL数据库(二)01-Redis数据类型——字符串类型之赋值与取值、递增数字、增加指定浮点数、向尾部追加值、获取字符串长度、设置键值 & 散列类型命令之赋值与取值、获取键值、删除字段、增加数字2024-12-01 14:09:07
  • NoSQL数据库(一)——redis的发展和特点 & Redis安装和配置文件redis.conf & redis命令行客户端2024-12-01 14:09:07
  • Node学习(九)062-管理系统之登录和注册-使用验证码——验证码插件-svg-captcha & 前端生成动态验证码图片 & 服务端验证验证码数据2024-12-01 14:09:07
  • 全屏图片