想象一下,有一个社交网络,这里有一个用于存储喜欢(喜欢)动作的表,不像是从这个表中删除:
CREATE TABLE IF NOT EXISTS post_likes(
post_id timeuuid,
liker_id uuid, //liker user_id
like_time timestamp,
PRIMARY KEY ((post_id) ,liker_id, like_time)
) WITH CLUSTERING ORDER BY (like_time DESC);
上表在Cassandra中存在问题,因为当liker_id
是第一个clustering_key
时,我们无法按第二个聚类键like_time
进行排序。
我们需要按like_time
对表格数据进行排序,我们会在用户想要查看谁喜欢这篇文章时使用它,并显示喜欢该帖子按时间排序的人员列表({{ 1}})
我们还需要删除(不像),我们需要再次like_time DESC
和post_id
你的建议是什么?我们如何按liker_id
对此表格进行排序?
答案 0 :(得分:1)
经过更多研究,我发现了这个解决方案: 选择正确的数据模型是使用Cassandra最困难的部分,这里是我们在Cassandra中为喜欢的表找到的解决方案,首先,我不得不说Cassandra的read和write路径非常快,你不必担心在你的Cassandra表上写字,你需要围绕你的查询建模并且记住,数据复制是可以的。您的许多表格可能会重复相同的数据。并且不要忘记在群集周围均匀分布数据,最大限度地减少读取的分区数量
由于我们使用的是NoSQL的Cassandra,我们知道NoSQL中的一个规则是非规范化,我们必须对数据进行非规范化,只考虑你想要的查询;这里对于类似的表数据建模我们将有两个表,这些表主要集中在易读或更容易说我们专注于我们想要的查询:
CREATE TABLE IF NOT EXISTS post_likes(
post_id timeuuid,
liker_id uuid, //liker user_id
like_time timestamp,
PRIMARY KEY ((post_id) ,liker_id)
);
CREATE TABLE IF NOT EXISTS post_likes_by_time(
post_id timeuuid,
liker_id uuid, //liker user_id
like_time timestamp,
PRIMARY KEY ((post_id), like_time, liker_id)
) WITH CLUSTERING ORDER BY (like_time DESC);
当用户喜欢帖子时,我们只需插入上述两个表格。
为什么我们有post_likes_by_time
表?
在社交网络中,您应该显示喜欢帖子的用户列表,通常您必须按like_time DESC
排序喜欢,因为您要按like_time
排序喜欢需要like_time
作为聚类键才能按时间排序喜欢。
那么我们为什么还有post_likes
表?
在post_likes_by_time
中,我们的群集密钥为like_time
,我们还需要删除之类的!当群集密钥为 like_time 时,我们在表格中对数据进行排序时,我们无法做到这一点。这就是我们也有post_likes
表
为什么你不仅可以有一个表并同时执行这两个操作,排序和删除?
要从post_likes
表格中删除一个,我们需要提供user_id
(此处为liker_id)和post_id
(一起),post_likes_by_time
我们需要like_time
like_time
作为聚类键,我们需要按liker_id
对表进行排序,然后它应该是第一个聚类键,第二个聚类键可能是like_time
,这就是重点! liker_id
是第一个群集密钥,然后按like_time
选择或删除,您还需要提供like_time
,但大部分时间都没有#include <time.h>
#include <stdio.h>
struct date {
int month;
int day;
int year;
};
struct date addSeven(struct date addSev) {
addSev.day += 7;
// Months with 31 days
if ((addSev.month == 1 || // January
addSev.month == 3 || // March
addSev.month == 5 || // May
addSev.month == 7 || // July
addSev.month == 8 || // August
addSev.month == 10 || // October
addSev.month == 12) // December
&& addSev.day > 31) {
addSev.day -= 31; // Equivalent to addSev.day = addSev.day - 31;
addSev.month += 1;
}
// Months with 30 days
else if ((addSev.month == 4 || // April
addSev.month == 6 || // June
addSev.month == 9 || // September
addSev.month == 11) // November
&& addSev.day > 30) {
addSev.day -= 30;
addSev.month += 1;
}
// February
else {
if (addSev.year % 4 == 0 && addSev.day > 29) { // Leap year
addSev.day -= 29;
addSev.month += 1;
}
else if (addSev.day > 28) {
addSev.day -= 28;
addSev.month += 1;
}
}
if ((addSev.day == 25)
&& addSev.day > 31) {
addSev.day -= 31; // Equivalent to addSev.day = addSev.day - 31;
addSev.month += 1;
}
else if ((addSev.day == 24)
&& addSev.day > 30) {
addSev.day -= 30;
addSev.month += 1;
}
else {
if (addSev.year % 4 == 0 && addSev.day > 29) { // Leap year
addSev.day -= 29;
addSev.month += 1;
}
else if (addSev.day > 28) {
addSev.day -= 28;
addSev.month += 1;
}
if (addSev.month > 12) {
addSev.month = 1; addSev.year += 1;
}
return addSev;
}
}
int main () {
struct date origDate, newDate;
newDate = addSeven (origDate);
printf("Enter a date in mm/dd/yyyy format:");
scanf("%d/%d/%d",&origDate.month,&origDate.day,&origDate.year);
printf("\n%d/%d/%d\n", origDate);
printf("\n%d/%d/%d\n", newDate);
return 0;
}
。