4

我使用下表:

CREATE TABLE IF NOT EXISTS lp_registry.domain (
    ownerid text,
    name1st text,
    name2nd text,
    name3rd text,
    registrar text,
    registered timestamp,
    expiration timestamp,
    updated timestamp,
    technologies list<text>,
    techversions list<text>,
    ssl boolean,
    PRIMARY KEY (
        (name1st, name2nd, name3rd), 
        registrar, ownerid, registered, expiration, updated
    )
);

表不会更新,只会添加新行。每次爬虫检查域时,都会添加新行。

我正在执行此选择:

SELECT * FROM lp_registry.domain WHERE 
    registrar = 'REG-WEDOS' AND 
    ownerid = 'FORPSI-JAF-S497436' 
ALLOW FILTERING;

但我想要的结果只是每个唯一“name3rd.name2nd.name1st”具有最新“更新”值的行。

如果我在标准 SQL 数据库中,我会使用带有 MAX 或 GROUP BY 的嵌套选择。但是,Cassandra 不支持此功能(Cassandra 中的MAX()、DISTINCT 和 group by)。但是我应该在 CQL 中做什么?

4

2 回答 2

3

应该修改整个架构。你正在做的SELECT,显然从你的应用程序的角度来看一个重要的不应该要求ALLOW FILTERING:你应该非规范化你的数据并创建一个表,其中registrarownerid是分区键。

在那个非规范化结构中,updated应该是一个分区键,用DESC. 然后查询将是

SELECT * FROM lp_registry.domain WHERE registrar='XXX' AND ownerid='YYY' LIMIT 10;

正如您所说的插入但从未更新的行,在您的应用程序中将新数据插入到多个非规范化表中(如有必要)应该不会很复杂。

Andy 的回答为您的表结构提供了更多详细信息和示例。

于 2016-01-02T12:53:58.790 回答
3

延伸到Cedric 的答案(这是一个很好的建议,并认为这是接受的答案),你会得到一个大致如下的表结构:

CREATE TABLE IF NOT EXISTS lp_registry.domain (
    ownerid text,
    name1st text,
    name2nd text,
    name3rd text,
    registrar text,
    registered timestamp,
    expiration timestamp,
    updated timestamp,
    technologies list<text>,
    techversions list<text>,
    ssl boolean,
    PRIMARY KEY ((registrar, ownerid), updated, name1st, name2nd, name3rd)
) WITH CLUSTERING ORDER BY (updated desc);

updated选择数据时,它将返回分区内您正在查询的注册商和 ownerid 的最新值的行。

此查询将非常快,因为您的数据将由注册商在磁盘上组织,所有者 ID 和行按更新的降序排列。

这是 cassandra 的一个关键概念,因为您的数据是根据您查询它的方式来组织的。您在查询中失去了灵活性,但您会感到很自在,因为您正在检索有组织的数据。这就是为什么根据查询对数据进行非规范化至关重要的原因。

如果您想检索所有数据的最新更新,事情变得复杂。这个问题不容易用 cassandra 解决,除非所有东西都共享同一个分区,该分区有自己的一组问题(使用“虚拟”分区键的示例策略)。

于 2016-01-02T17:58:44.207 回答