Cassandra 和 <=, => 日期运算符,不允许过滤

标签 cassandra cql

我是 cassandra 的菜鸟,我不明白为什么我不能按日期过滤(想要返回日期之间的结果),例如:

CREATE TABLE test.service_bar(
    service_bar_id UUID,
    start_date_time timestamp,
    end_date_time timestamp,
    title varchar,
    message text,
    is_active boolean,
    PRIMARY KEY((start_date_time, end_date_time))
);

然后这个工作:

  SELECT start_date_time, end_date_time, is_active, message, service_bar_id, title
  FROM test.service_bar
  WHERE start_date_time = '2019-10-30 14:10:29'  AND end_date_time = '2019-10-30 14:10:29'
  LIMIT 500;

但是这个剂量

  SELECT start_date_time, end_date_time, is_active, message, service_bar_id, title
  FROM test.service_bar
  WHERE start_date_time >= '2019-10-30 14:10:29'  AND end_date_time <= '2019-10-30 14:10:29'
  LIMIT 500;

我无法使用允许过滤

我如何在 Cassandra 中执行此类查询?

最佳答案

I dont understand why I cant filtering by dates (wanna return result between date)

您所看到的行为是因为:

PRIMARY KEY((start_date_time, end_date_time))

您已将 start_date_timeend_date_time 定义为复合分区键。由于 Cassandra 使用分布式哈希来确保正确的数据分布,因此分区不会按其值的顺序存储。它们通过分区键的哈希 token 值存储。您可以通过在分区键上使用 token 函数来查看这一点:

aaron@cqlsh:stackoverflow> SELECT token(start_date_time,end_date_time),start_date_time,end_date_time,service_bar_id FROM service_bar ;

 system.token(
     start_date_time,
     end_date_time)   | start_date_time                 | end_date_time                   | service_bar_id
----------------------+---------------------------------+---------------------------------+--------------------------------------
    26346508703811310 | 2019-10-30 19:10:29.000000+0000 | 2019-10-30 19:10:29.000000+0000 | 49a70440-8689-4248-b389-13b8d0373e58
  1488616260313758762 | 2019-11-01 19:10:29.000000+0000 | 2019-11-01 19:10:29.000000+0000 | b0bab610-a285-41e7-ba5c-d56f8fb12f52
  2185622653117187064 | 2019-10-30 21:10:29.000000+0000 | 2019-10-30 21:10:29.000000+0000 | 3686c6a6-fd8d-4247-b501-964363a48f63
  7727638696734890177 | 2019-10-30 20:10:29.000000+0000 | 2019-10-30 20:10:29.000000+0000 | 97fc799e-fb54-4b7f-956e-f06bcb9e9d9d

(4 rows)

这是行的默认顺序。这样做是因为每个节点负责特定的 token 范围,以确保数据在多节点集群中尽可能均匀地分布(这是通常的生产用例)。因此,CQL 对查询分区键的方式有一些限制。这些限制是为了防止您编写错误的查询...例如不允许对分区键进行范围查询。

how I can do such queries in Cassandra?

这还应该告诉您,您应该构建表和查询,以确保它们可以通过对单个节点的请求来完成。鉴于此,只有更改分区键,您的用例才会真正起作用。

开发团队实现像您这样的解决方案的一种方法是使用称为“时间分桶”或有时只是“分桶”的建模技术。在这种情况下,假设您每月编写的条目永远不会超过几千条。也许情况并非如此,但我将在本示例中使用它。然后,我可以按月进行分区,然后使用 _time 列作为聚类键。

CREATE TABLE stackoverflow.service_bar_by_month (
    month_bucket int,
    start_date_time timestamp,
    end_date_time timestamp,
    is_active boolean,
    message text,
    service_bar_id uuid,
    title text,
    PRIMARY KEY (month_bucket, start_date_time, end_date_time)
) WITH CLUSTERING ORDER BY (start_date_time DESC, end_date_time DESC);

这将按 month_bucket 的值将所有行存储在一起,并且在每个分区内,行将按 start_date_timeend_date_time 排序按降序排列。现在可以了:

aaron@cqlsh:stackoverflow> SELECT start_date_time, end_date_time, is_active, message, service_bar_id, title
                 ... FROM service_bar_by_month
                 ... WHERE month_bucket = 201910 AND start_date_time >= '2019-10-30 14:10:29'  AND start_date_time <= '2019-10-31 23:59:59';

 start_date_time                 | end_date_time                   | is_active | message           | service_bar_id                       | title
---------------------------------+---------------------------------+-----------+-------------------+--------------------------------------+--------
 2019-10-30 21:10:29.000000+0000 | 2019-10-30 21:10:29.000000+0000 |      True | This is an alert3 | eae5d3be-b2b2-40a1-aa28-0412fe9c18e6 | alert3
 2019-10-30 20:10:29.000000+0000 | 2019-10-30 20:10:29.000000+0000 |      True | This is an alert2 | af4ec72f-7758-42ef-b731-8d08f8a00006 | alert2
 2019-10-30 19:10:29.000000+0000 | 2019-10-30 19:10:29.000000+0000 |      True | This is an alert1 | 8b13db5c-9e39-4ee5-90a9-64758c5ab5be | alert1

(3 rows)

但请注意,您只能对单个集群键强制执行范围查询,如上面的 start_date_time 。这是行不通的:

AND start_date_time >= '2019-10-30 14:10:29'  AND end_date_time <= '2019-10-31 23:59:59';

它无法工作,因为 Cassandra 被设计为按顺序从磁盘读取数据或将数据写入磁盘。允许在单个查询中对多个列进行范围查询将需要 Cassandra 进行随机读取,而这是它不擅长的。您可以使用 ALLOW FILTERING 指令来实现此目的,但不建议这样做。不过,在小分区内使用ALLOW FILTERING可能会表现良好。

关于Cassandra 和 <=, => 日期运算符,不允许过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58644485/

相关文章:

cassandra - 如何使用 CQL (Cassandra) 查询集合中用户定义类型的字段

python - 模拟函数调用实际函数

mysql - mysql和cassandra的区别

cassandra - Cassandra 可以分区表吗?

cassandra - Cassandra 可以保存空列表吗?

java - 我们如何将 com.datastax.driver.core.LocalDate 转换为 java.util.Date?

cassandra - 如何使用 CQL 语句获取特定表的主键/聚集列名称?

cassandra - python cassandra 驱动程序 : Error attempting to reconnect

python - 是否可以使用 ScyllaDB for python 更有效地添加数据?

Cassandra - 如何确保pk仅由一个人更新