Я не понимаю, почему я не могу фильтровать по датам (хочу вернуть результат между датами)
Поведение, которое вы видите, из-за этого:
PRIMARY KEY((start_date_time, end_date_time))
Вы определили start_date_time
и end_date_time
как ключ составного раздела. Поскольку Cassandra использует распределенный хеш для обеспечения правильного распределения данных, разделы не сохраняются в порядке их значений. Они хранятся в хешированном значении ключа ключа раздела. Это можно увидеть с помощью функции 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)
Это порядок по умолчанию для ваших строк. Это сделано потому, что каждый узел отвечает за определенные диапазоны токенов, чтобы гарантировать, что данные распределены как можно более равномерно в многоузловом кластере (что является обычным производственным сценарием использования). Из-за этого у CQL есть некоторые ограничения на то, как вы можете запрашивать ключи разделов. Эти ограничения введены для того, чтобы избавить вас от написания неверных запросов ... например, запрет на запросы диапазона для ключей раздела.
как я могу выполнять такие запросы в 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_time
и end_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 предназначена для последовательного чтения и записи данных с / на диск. Разрешение запросов диапазона для нескольких столбцов в одном запросе потребует от Кассандры случайного чтения, что просто не очень хорошо. Вы можете сделать это сделать с помощью директивы ALLOW FILTERING
, но это не рекомендуется. Хотя использование ALLOW FILTERING
в небольших разделах, вероятно, будет работать нормально.