由于 Cassandra 需要基于查询的建模方法,我们需要专门构建一个表来处理此查询:
SELECT * FROM scala_fireman.fireman
WHERE temperature > 0 ORDER BY date LIMIT 5 ALLOW FILTERING;
你有没有通过uuid查询?如果是这样,那么我们可以建立一个新表。如果没有,您将需要更改您的主键才能使其正常工作。在 ID 列上构建单个 PRIMARY KEY 会严重限制您的查询灵活性(正如您所发现的那样)。
这是一个尽可能多的 POC,目前我派出了 100 万消防员
这将是你的第一个障碍。 Cassandra 每个分区只能支持 20 亿个单元,而且在此之前它会变慢。因此,我们希望通过“时间分段”来限制每个分区的消防员事件数量。例如,我将使用 month_bucket,但您应该确定这是否真的适合您的业务需求。
接下来,您想要ORDER BY 日期,因此我们将使用它作为集群键。实际上,由于date 是一个文本字段,我们将使用time,因为我确定您不希望结果以ASCII-betical 顺序返回。 ORDER BY 子句的快速教育是它完全是多余的。您可以仅按照集群键的预定顺序强制执行它。它不应该出现在查询中。
注意:您收到您所看到的错误的原因是,排序顺序只能在数据分区内执行。它不能在结果集上强制执行。
另外,我看到您正在对temperature 进行开放式范围查询。通常,这是一个坏主意(也是您在原始查询中需要 ALLOW FILTERING 的原因)。但是在一个分区内,应该不会太差。只要那个分区不是太大。我们也会对此进行聚类。
当然,多个消防员可能会在同一天、同一温度下参与同一事件,因此我们将在末尾添加 uuid 以确保唯一性。您的新主键应如下所示:
PRIMARY KEY ((month_bucket),time,temperature,uuid))
所以如果尝试这个表定义:
create table fireman_events_by_date_and_temp (
uuid uuid,
month_bucket int,
date text,
heartrate int,
id text,
location text,
ratecommunication int,
temperature int,
time timestamp,
PRIMARY KEY ((month_bucket),time,temperature,uuid))
WITH CLUSTERING ORDER BY (time DESC, temperature ASC, uuid ASC);
现在,如果我加载一些数据并运行您的查询:
> SELECT time,temperature,heartrate,location
FROM fireman_events_by_date_and_temp
WHERE month_bucket=201904
AND temperature > 0
LIMIT 5
ALLOW FILTERING;
time | temperature | heartrate | location
---------------------------------+-------------+-----------+----------
2019-04-30 13:40:03.253000+0000 | 644 | 144 | SF
2019-04-30 13:39:51.944000+0000 | 644 | 144 | SF
2019-04-30 13:39:39.859000+0000 | 644 | 144 | SF
2019-04-30 13:39:30.331000+0000 | 644 | 144 | SF
2019-04-30 13:39:15.945000+0000 | 644 | 144 | NY
(5 rows)
通常,我不建议使用ALLOW FILTERING。但只要您查询分区键 (month_bucket),所有数据仍应由同一节点提供服务。
另外,我在 2015 年写了这篇关于 Cassandra 中结果集排序的文章,并在其中演示了这些建模技术的使用。四年后它仍然很重要(尤其是对于这样的问题):
We Shall Have Order!
阅读一下,看看是否有帮助。