尽管WITH CLUSTERING ORDER BY,查询结果仍未排序

时间:2014-11-10 21:35:33

标签: cassandra cql

我正在存储表中所有用户的帖子。我想从用户关注的所有用户中检索帖子。

CREATE TABLE posts (
  userid int,
  time timestamp,
  id uuid,
  content text,
  PRIMARY KEY (userid, time)
)WITH CLUSTERING ORDER BY (time DESC)

我有关于所有用户在另一个表中关注的人的数据

CREATE TABLE follow (
  userid int,
  who_follow_me set<int>,
  who_i_follow set<int>,
  PRIMARY KEY ((userid))
) 

我正在进行查询

select * from posts where userid in(1,2,3,4....n);

2个问题:

  1. 为什么我仍然以随机顺序获取数据,尽管在帖子中指定了CLUSTERING ORDER BY。 ?
  2. 模型是否正确以最佳地满足查询(用户可以拥有n个粉丝)?
  3. 我正在使用Cassandra 2.0.10。

2 个答案:

答案 0 :(得分:3)

“为什么我仍然按随机顺序获取数据,虽然在帖子中指定了CLUSTERING ORDER BY?”

这是因为ORDER BY仅适用于特定分区键中的行。因此,在您的情况下,如果您想查看特定用户的所有帖子,请执行以下操作:

SELECT * FROM posts WHERE userid=1;

返回time排序的结果,因为userid=1分区键中的所有行都会被它聚集。

“模型是否正确以最佳地满足查询(用户可以拥有n个粉丝)?”

只要您不关心按时间戳排序的结果,它就可以正常工作。为了能够查询按时间排序的所有用户的帖子,您需要提供不同的分区键。如果不了解您的应用程序,可以使用GROUP之类的列(例如)和分区。

因此,假设您将所有用户均匀分配到八个组:A,B,C,D,E,F,G和H.假设您的表格设计更改为:

CREATE TABLE posts (
  group text,
  userid int,
  time timestamp,
  id uuid,
  content text,
  PRIMARY KEY (group, time, userid)
)WITH CLUSTERING ORDER BY (time DESC)

然后,您可以查询B组所有用户的所有帖子,如下所示:

SELECT * FROM posts WHERE group='B';

这将为您提供B组中所有用户的所有帖子,按时间排序。所以基本上,为了让你的查询按时间适当地订购帖子,你需要将你的帖子数据划分为除了用户ID之外的其他东西。

修改

PRIMARY KEY (userid, follows)) WITH CLUSTERING ORDER BY (created DESC);

那不行。实际上,这应该产生以下错误:

  

code = 2200 [无效查询] message =“列中缺少CLUSTERING ORDER”

即使您确实在follows条款中添加了CLUSTERING ORDER,您也会看到:

  

code = 2200 [无效查询] message =“只能在CLUSTERING ORDER指令中定义聚类键列”

CLUSTERING ORDER子句只能用于群集列,在这种情况下,只有follows列。将您的PRIMARY KEY定义更改为follows(ASC)和created(DESC)上的群集。我已对此进行了测试,并插入了一些示例数据,并且可以看到此查询有效:

aploetz@cqlsh:stackoverflow> SELECT * FROM posts WHERE userid=2 AND follows=1;

 userid | follows | created                  | id
--------+---------+--------------------------+--------------------------------------
      2 |       1 | 2015-01-25 13:27:00-0600 | 559cda12-8fe7-45d3-9a61-7ddd2119fcda
      2 |       1 | 2015-01-25 13:26:00-0600 | 64b390ba-a323-4c71-baa8-e247a8bc9cdf
      2 |       1 | 2015-01-25 13:24:00-0600 | 1b325b66-8ae5-4a2e-a33d-ee9b5ad464b4

(3 rows)

但是,如果您只想userid查询,则可以查看所有关注者的帖子。但在这种情况下,帖子只会在每个关注者中订购,如下所示:

aploetz@cqlsh:stackoverflow> SELECT * FROM posts WHERE userid=2;

 userid | follows | created                  | id
--------+---------+--------------------------+--------------------------------------
      2 |       0 | 2015-01-25 13:28:00-0600 | 94da27d0-e91f-4c1f-88f2-5a4bbc4a0096
      2 |       0 | 2015-01-25 13:23:00-0600 | 798053d3-f1c4-4c1d-a79d-d0faff10a5fb
      2 |       1 | 2015-01-25 13:27:00-0600 | 559cda12-8fe7-45d3-9a61-7ddd2119fcda
      2 |       1 | 2015-01-25 13:26:00-0600 | 64b390ba-a323-4c71-baa8-e247a8bc9cdf
      2 |       1 | 2015-01-25 13:24:00-0600 | 1b325b66-8ae5-4a2e-a33d-ee9b5ad464b4

(5 rows)

答案 1 :(得分:1)

这是我的新架构,

CREATE TABLE posts(id uuid, 
userid int,
follows int,
created timestamp,
PRIMARY KEY (userid, follows)) WITH CLUSTERING ORDER BY (created DESC);

这里userid表示发布它的人,以及follow表示他的跟随者之一的userid。假设用户x跟随其他10个人,我正在进行10 + 1次插入。绝对有太多的数据重复。但是现在更容易获得具有以下查询的用户之一的时间线

select * from posts where follows=?