在Cassandra上写入和更新记录以及聚类列

时间:2016-11-18 17:39:26

标签: cassandra cqlsh nosql

我有一个通知表和附加索引

CREATE TABLE notification (
    postid double,
    userid double,
    type text,
    message text,
    hasread boolean,
    postdate timestamp,
    PRIMARY KEY (userid, postdate)
)  WITH  CLUSTERING ORDER BY (postdate DESC);

CREATE INDEX postid ON notification(postid);

假设我插入了几行

select * from notification;

 userid | postdate                        | hasread | message                | postid | type
--------+---------------------------------+---------+------------------------+--------+---------
    104 | 2016-11-18 17:21:32.692000+0000 |   False | Let\'s do it together! |  70521 | newpost
    104 | 2016-11-18 17:21:26.511000+0000 |   False | Let\'s do it together! |  90521 | newpost
    103 | 2016-11-18 17:20:17.284000+0000 |   False | Let\'s do it together! |  40521 | newpost
    103 | 2016-11-18 17:20:02.925000+0000 |   False | Let\'s do it together! |  40521 | newpost
    103 | 2016-11-18 17:19:55.643000+0000 |   False | Let\'s do it together! |  30521 | newpost
    103 | 2016-11-18 17:19:49.029000+0000 |   False | Let\'s do it together! |  60521 | newpost

如果我做简单的查询,即

select * from notification where postid=40521;

然后结果似乎很好

userid | postdate                        | hasread | message                | postid | type
--------+---------------------------------+---------+------------------------+--------+---------
    103 | 2016-11-18 17:20:17.284000+0000 |   False | Let\'s do it together! |  40521 | newpost
    103 | 2016-11-18 17:20:02.925000+0000 |   False | Let\'s do it together! |  40521 | newpost

或者让我们像这样获得一行

select * from notification where postid=60521;

再一次单行似乎很好

userid | postdate                        | hasread | message                | postid | type
--------+---------------------------------+---------+------------------------+--------+---------
    103 | 2016-11-18 17:19:49.029000+0000 |   False | Let\'s do it together! |  60521 | newpost

但是,当我在一行中更新hasread行时,我错过了postdate错误,这是聚类列

update notification set hasread=true where postid=60521 and userid=103;
InvalidRequest: Error from server: code=2200 [Invalid query] message="Some clustering keys are missing: postdate"

我需要按排序顺序获取列表,这就是我必须使用postdate进行群集列的原因。 但是,同时我需要更新特定的行。我想这是关于设计,但仍然无法弄明白。任何建议,将不胜感激。

2 个答案:

答案 0 :(得分:2)

在Cassandra中更新行时,您必须提供整个PRIMARY KEY。这基本上是错误消息告诉你的。请记住,Cassandra NOT 是一个关系数据库,因此您 NOT 无法通过postid进行更新。

此外,重要的是要记住Cassandra不区分INSERT和UPDATE。由于特定行的唯一性由其完整的PRIMARY KEY确定,因此必须为所有upsert提供所有PRIMARY KEY组件。从本质上讲,这就是你需要做的事情:

UPDATE notification SET hasread=true 
  WHERE userid=103 AND postdate='2016-11-18 17:19:49.029+0000';

此外,postid似乎是一个高基数列。因此,依赖于该二级索引的调用不会表现良好。像一样。如果您确实需要按postid进行查询,则应考虑为该模式构建其他查询表。

答案 1 :(得分:1)

您无法通过将非主要列指定为where子句来更新或删除。

  

WHERE子句指定要更新的行。要指定行,WHERE子句必须为行的主键的每一列提供值。要指定多行,可以使用IN关键字引入可能值的列表。您只能对主键的最后一列执行此操作。

让postid = 60521和userid = 103更新hasread 首先您需要选择过期日

SELECT postdate FROM notification where postid=60521 and userid=103;

您将获得postdate。现在,您可以使用userid和postdate更新hasread字段

update notification set hasread=true where userid=103 and postdate=?;