Ответ 1
Запросы по диапазонам - это прикольный вопрос. Способ выполнения запроса реального диапазона заключается в использовании составного первичного ключа, который делает диапазон для части кластеризации. Поскольку диапазон находится в части кластеризации, вы не можете выполнять запрошенные вами запросы: вам нужно, по крайней мере, иметь равное условие для всего ключа раздела. Рассмотрим пример:
CREATE TABLE users (
mainland text,
state text,
uid int,
name text,
zip int,
PRIMARY KEY ((mainland), state, uid)
)
Теперь uid является int просто для облегчения тестирования
insert into users (mainland, state, uid, name, zip) VALUES ( 'northamerica', 'washington', 1, 'john', 98100);
insert into users (mainland, state, uid, name, zip) VALUES ( 'northamerica', 'texas', 2, 'lukas', 75000);
insert into users (mainland, state, uid, name, zip) VALUES ( 'northamerica', 'delaware', 3, 'henry', 19904);
insert into users (mainland, state, uid, name, zip) VALUES ( 'northamerica', 'delaware', 4, 'dawson', 19910);
insert into users (mainland, state, uid, name, zip) VALUES ( 'centraleurope', 'italy', 5, 'fabio', 20150);
insert into users (mainland, state, uid, name, zip) VALUES ( 'southamerica', 'argentina', 6, 'alex', 10840);
Теперь запрос может выполнить то, что вам нужно:
select * from users where mainland = 'northamerica' and state > 'ca' and state < 'ny';
Выход
mainland | state | uid | name | zip
-------------+----------+-----+--------+-------
northamerica | delaware | 3 | henry | 19904
northamerica | delaware | 4 | dawson | 19910
если вы поместили int (age, zipcode) в качестве первого столбца ключа кластеризации, вы можете выполнять одни и те же запросы, сравнивая целые числа.
УБЕДИТЕСЬ: большинство людей, глядя на эту ситуацию, начинают думать: "Хорошо, я могу поставить поддельный ключ раздела, который всегда один и тот же, а затем я могу выполнять запросы диапазона". Это огромная ошибка, ключ раздела отвечает за распределение данных по узлам. Установка ключа фиксированного раздела означает, что все данные будут завершены в том же node (и в его реплике).
Разделение мировой зоны на зоны 15/20 (для того, чтобы иметь ключ раздела 15/20) - это нечто, но этого недостаточно, и сделано только для создания допустимого примера.
EDIT: из-за изменения вопроса
Я не сказал, что это единственная возможность; если вы не можете найти правильный способ разделить пользователей и выполнить такой запрос, это одна из возможностей, а не единственная. Запросы диапазона должны выполняться при кластеризации ключевой части. Слабой точкой AGE в качестве ключа раздела является то, что вы не можете выполнить ОБНОВЛЕНИЕ над ним, в любое время, когда вам нужно обновить возраст пользователя, который вы должны выполнить, удалить и вставить (альтернативой может быть запись birth_year/birth_date, а не возраст, а затем рассчитать клиентскую сторону)
Чтобы ответить на вопрос о добавлении вторичного индекса: на самом деле запросы по вторичному индексу не поддерживают оператор IN. Из сообщения CQL, похоже, скоро они будут развиваться.
Неверный запрос: предикаты IN для столбцов не первичного ключа (xxx) еще не установлены поддерживается
Однако, даже если вторичный индекс будет поддерживать оператор IN, ваш запрос не изменится с
select * from users where age IN (15,16,17,....30)
Просто, чтобы прояснить мою концепцию: все, что не имеет "чистого" и "готового" решения, требует усилий пользователя моделировать данные таким образом, чтобы удовлетворить его потребности. Чтобы сделать пример (я не говорю, что это хорошее решение: я бы не использовал его)
CREATE TABLE users (
years_range text,
age int,
uid int,
PRIMARY KEY ((years_range), age, uid)
)
введите некоторые данные
insert into users (years_range, age , uid) VALUES ( '11_15', 14, 1);
insert into users (years_range, age , uid) VALUES ( '26_30', 28, 3);
insert into users (years_range, age , uid) VALUES ( '16_20', 16, 2);
insert into users (years_range, age , uid) VALUES ( '26_30', 29, 4);
insert into users (years_range, age , uid) VALUES ( '41_45', 41, 5);
insert into users (years_range, age , uid) VALUES ( '21_25', 23, 5);
данные запроса
select * from users where years_range in('11_15', '16_20', '21_25', '26_30') and age > 14 and age < 29;
Выход
years_range | age | uid
-------------+-----+-----
16_20 | 16 | 2
21_25 | 23 | 5
26_30 | 28 | 3
Это решение может решить вашу проблему и может быть использовано в небольшом кластере, где около 20 ключей (0_5... 106_110) могут иметь хороший дистрибутив. Но это решение, как и раньше, не позволяет ОБНОВИТЬ и уменьшает распределение ключа. Преимущество состоит в том, что у вас есть небольшие блоки IN.
В идеальном мире, где SI уже разрешает предложение IN, я бы использовал UUID в качестве ключа раздела years_range (задано как birth_year_range) как SI и "фильтровал" мою клиентскую часть данных (если вас интересует возраст 10 > 22 я просил бы IN('1991_1995', '1996_2000', '2001_2005', '2006_2010', '2011_2015')
вычислять и удалять неиспользуемые годы в моем приложении)
НТН, Carlo