我正在尝试锻炼如何在Cassandra中创建模型,以便以某种有效的方式(可能是单个查询)获取信息,即当前登录的用户是否喜欢帖子以及帖子数据。在RDMBS中,这很容易,但是我只是不敢在Cassandra中做到这一点。
以下是我要在RDMBS上的Cassandra中实现的示例:
SELECT
x.post_id,
x.content,
x.created_at,
(
SELECT CASE
WHEN EXISTS (
SELECT 1
FROM post_likes AS p1
WHERE (p1.user_id = @currentUserId) AND (x.post_id = p1.post_id))
THEN TRUE::bool ELSE FALSE::bool
END
) AS "has_current_user_liked_post"
答案 0 :(得分:0)
最简单的方法是创建表likes_by_post:
CREATE TABLE likes_by_post (
post_id text,
user_id text,
PRIMARY KEY (post_id, user_id)
);
此表将使您获得喜欢某个帖子的所有用户:
SELECT * FROM likes_by_post WHERE post_id='post_1';
检查用户喜欢的帖子:
SELECT * FROM likes_by_post WHERE post_id='post_1' AND user_id='user_1';
但是此方法有一个缺点-如果您希望每个帖子有很多用户喜欢(数百万或数十亿),则该表的分区太大,将导致性能不佳和无法存储每个帖子如此多的喜欢。 Cassandra的每个分区键限制为20亿行。
在这种情况下,您可以使用复合主键将有关单个帖子的喜欢信息分散到多个分区(这种方法通常称为“一致性哈希”):
CREATE TABLE likes_buckets_by_post (
post_id text,
bucket_id int,
user_id text,
PRIMARY KEY (( post_id, bucket_id ), user_id)
);
bucket_id
是一个综合字段,负责为同一帖子的不同用户生成不同的分区键。
bucked_id
应该是基于user_id
字段的某种哈希。
一致的哈希提供了根据指定的用户ID在指定范围内生成一些数字的能力。 (例如Guava Java库提供了consistent hashing function)
在将数据插入likes_buckets_by_post
表之前,您需要使用一致的哈希函数和指定数量的存储桶来计算bucket_id
:
var bucket = consistentHash(user_id, N)
在N是存储桶总数的情况下,该数目取决于您的条件:您拥有多少个Cassandra节点,您希望每个帖子有多少喜欢,这个数字越大,将散布用于存储的更多分区。
请注意,如果您需要为帖子要求所有赞,则必须执行N次请求,但对于您的情况,只需要一个请求即可检查单个用户(如一篇帖子)。
INSERT INTO likes_buckets_by_post (post_id, bucket_id, user_id) VALUES ('post_1', bucket, 'user_1' );
在选择数据之前,还需要使用与插入相同的参数来计算哈希值:
var bucket = consistentHash(user_id, N)
然后您可以检查喜欢发贴的用户:
SELECT * FROM likes_buckets_by_post WHERE post_id='post_1' AND bucket_id=bucket AND user_id='user_1';