Cassandra/Scylla DB按主题创建时间进行端到端排序,按多个类别过滤主题

p8h8hvxi  于 2023-04-30  发布在  Cassandra
关注(0)|答案(3)|浏览(215)

假设有一个主题表:

CREATE TABLE topic(
  group text,
  ctegory text,
  created_at timestamp
)

主题分组。每个主题属于一个类别。主题有创建日期。
需要选择与给定类别匹配的主题(在给定组中),并且结果列表必须仅按创建日期排序(不包括类别)。
如果我像这样设置键(见下文),类别列表将不仅按created_at排序,而是首先按category排序,然后按created_at排序

PRIMARY KEY (group , category, created_at )

select * from topic where group =... and category in ('A','B','C')

如果我像这样设置键(见下文),那么不指定created_at就不可能执行请求

PRIMARY KEY (group,created_at,category )

select * from topic where group =... and  category in ('A','B','C')

如果我在category字段上创建辅助索引,它将不能使用IN操作符在select startment中指定多个category。..
我应该如何组织给定选择场景的数据模型(表结构、主键,可能还有辅键)?

7gs2gvoe

7gs2gvoe1#

您是否已经尝试过使用created_at作为集群列,以便在插入时进行排序?您可以根据需要使用升序或降序,例如:

CREATE TABLE topic(
    group text,
    category text,
    created_at timestamp
    PRIMARY KEY (group , category), created_at )
  )WITH CLUSTERING ORDER BY (created_at DESC);
mefy6pfw

mefy6pfw2#

@colesico,我在这里利用了Paul的数据模型模式。忽略使用的列名和表名。
但是如果使用IN操作符(i.e.类别IN('A','B'))-不执行通过created_at的排序
它将被正确地排序 * 在一个给定的分区 *。这是一个演示。我使用Astra DB快速地得出了这个例子。
创建表格:

token@cqlsh:payloadtest> create table so20230427(g text,c text, ct timestamp, primary key((g,c),ct)) with clustering order by (ct desc);

插入了一堆记录:

token@cqlsh:payloadtest> select * from so20230427 ;

 g | c | ct
---+---+---------------------------------
 1 | 2 | 2023-04-27 16:49:30.172000+0000
 1 | 2 | 2023-04-27 16:49:29.407000+0000
 1 | 2 | 2023-04-27 16:49:27.480000+0000
 1 | 1 | 2023-04-27 16:49:15.788000+0000
 1 | 1 | 2023-04-27 16:49:14.605000+0000
 1 | 1 | 2023-04-27 16:49:02.751000+0000

(6 rows)

当我查询时,我可以很好地看到ct列按照我需要的顺序i排序。即按降序排列。

token@cqlsh:payloadtest> select * from so20230427 where g='1' and c='1';

 g | c | ct
---+---+---------------------------------
 1 | 1 | 2023-04-27 16:49:15.788000+0000
 1 | 1 | 2023-04-27 16:49:14.605000+0000
 1 | 1 | 2023-04-27 16:49:02.751000+0000

(3 rows)
token@cqlsh:payloadtest> select * from so20230427 where g='1' and c in ('1','2');

 g | c | ct
---+---+---------------------------------
 1 | 1 | 2023-04-27 16:49:15.788000+0000
 1 | 1 | 2023-04-27 16:49:14.605000+0000
 1 | 1 | 2023-04-27 16:49:02.751000+0000
^^^^ The records are sorted within the partition of ('1','1') ^^^
 1 | 2 | 2023-04-27 16:49:30.172000+0000
 1 | 2 | 2023-04-27 16:49:29.407000+0000
 1 | 2 | 2023-04-27 16:49:27.480000+0000
^^^^ The records are sorted within the partition of ('1','2') ^^^

(6 rows)

你在这里还缺少什么或者需要完成什么?您是否希望在所有分区上完成排序(即:即groupcategory分区组合)?如果是这样,你必须在你的应用程序中这样做。

polhcujo

polhcujo3#

我认为最适合您的模式是PRIMARY KEY (group,category,created_at)(与您建议的顺序相反),甚至是((group,category),created_at)。换句话说,对于每个组/类别组合,您可以有效地检索按日期排序的特定类别的结果列表。
然后,您可以获取每个类别“A”,“B”和“C”的结果,每个类别都将按数据排序,并且您可以有效地合并这三个排序的结果流以获得一个排序的结果流。
如果你做了unpaged请求(只有当你知道你期待的是1000个结果,而不是100万个结果时才有意义),你甚至可以让Cassandra或Scylla用带有IN和ORDER BY的SELECT为你重新排序结果(如果你做分页,这是不支持的)。但是在客户机中进行这种合并也非常容易,因为它只需要一个简单的合并,甚至不需要一个完整的排序。

相关问题