InvalidRequest: code=2200 [Invalid query] message=Invalid operator ›= for PRIMARY KEY part

У меня есть следующий набор данных в cassandra:

Структура таблицы

CREATE TABLE userlog (
 term text,
 ts timestamp,
 year int,
 month int,
 day int,
 hour int,
 weekofyear int,
 dayofyear int,
 count counter,
 PRIMARY KEY (term, ts, year,month,day,hour,weekofyear,dayofyear)
);

.

term             | ts                       | year | month | day | hour | weekofyear | dayofyear | count
------------------+--------------------------+------+-------+-----+------+------------+-----------+-------
www.datastax.com | 2028-07-13 17:06:28+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     2
www.datastax.com | 2015-07-28 16:17:36+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     6
www.datastax.com | 2015-07-28 16:17:36+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     2
www.datastax.com | 2015-07-28 16:17:36+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     2
www.datastax.com | 2015-07-28 16:21:15+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     2
www.datastax.com | 2015-07-28 16:21:33+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     2
www.datastax.com | 2015-07-28 16:21:50+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     2
www.datastax.com | 2015-07-28 16:21:52+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     2
www.datastax.com | 2015-07-28 16:21:53+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     2
             www | 2015-07-28 16:46:00+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     2
            www. | 2015-07-28 16:47:00+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     2
            www. | 2015-07-28 16:48:00+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     2
            www. | 2015-07-28 16:50:00+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     2
            www. | 2015-07-28 16:55:00+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     2

Когда я запускаю этот запрос:

SELECT * FROM userlog  WHERE ts >= '2015-07-28 16:46' AND  ts <= '2015-07-28 16:55' ALLOW FILTERING;

Я получаю правильный результат:

term | ts                       | year | month | day | hour | weekofyear | dayofyear | count
------+--------------------------+------+-------+-----+------+------------+-----------+-------
www  | 2015-07-28 16:46:00+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     2
www. | 2015-07-28 16:47:00+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     2
www. | 2015-07-28 16:48:00+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     2
www. | 2015-07-28 16:50:00+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     2
www. | 2015-07-28 16:55:00+0530 | 2015 |     7 |  28 |   16 |         31 |       209 |     2

но когда я пытаюсь удалить строки с теми же условиями

DELETE FROM userlog WHERE ts >= '2015-07-28 16:46' AND  ts <= '2015-07-28 16:55';

Выдает следующую ошибку:

InvalidRequest: code=2200 [Invalid query] message="Invalid operator >= for PRIMARY KEY part ts"

Я что-то упускаю ? Как удалить данные в указанном временном диапазоне? Кроме того, есть ли способ получить данные в указанном диапазоне времени (кроме того, что я делаю?)


person Ritesh Sinha    schedule 28.07.2015    source источник


Ответы (1)


Команда DELETE не поддерживает запросы диапазона или предложение ALLOW FILTERING. Из документации он поддерживает только операторы = и IN:

Вы можете удалить отдельную строку, полностью указав как раздел, так и столбцы кластеризации.

Вы можете удалить весь раздел, просто указав ключ раздела.

И вы можете использовать оператор IN, чтобы сделать несколько из них одновременно.

Если вы хотите выборочно удалить строки из раздела, вы можете сначала запросить их с помощью SELECT, а затем в своем приложении выполнить удаление для каждой строки, возвращенной из SELECT.

Обычно вы не хотите использовать ALLOW FILTERING в своих операторах SELECT, поскольку это очень неэффективно, поэтому обычно вы указываете ключ раздела при выполнении запроса диапазона SELECT. Вы должны структурировать свою схему так, чтобы информация, необходимая для операции, находилась в известных разделах, чтобы вам не нужно было выполнять полное сканирование таблицы, чтобы найти что-то.

person Jim Meyer    schedule 28.07.2015
comment
If you want to selectively delete rows from within a partition, you could first query for them using SELECT and then in your application issue a delete for each row returned from the SELECT. Как это сделать?Как передать результаты выбора в операторы удаления? - person Ritesh Sinha; 28.07.2015
comment
Я могу выполнить итерацию и получить результаты ResultSet result = session.execute(insertUpdateTable); while(result.iterator().hasNext()) { System.out.println(result.one()); } Как передать оператор удаления? - person Ritesh Sinha; 28.07.2015
comment
Отличный ответ Джим! CQL DELETE вызывает много путаницы, поэтому приятно видеть его таким образом. - person Aaron; 28.07.2015
comment
@user-4870385 user-4870385 При переборе полученных строк вы должны использовать QueryBuilder для создания соответствующего оператора удаления, считывая значения столбцов каждой строки результата. Затем вы должны выполнять операторы удаления асинхронно, чтобы они были конвейеризированы для быстрого выполнения. - person Jim Meyer; 28.07.2015