2017-02-07 21 views
0

У меня есть таблица вроде этого:Как выбрать строки фильтруются более чем одной записи в карте Colum (Cassandra 3.9)

CREATE TABLE test.products (
id uuid PRIMARY KEY, 
name text, 
params map<text, text>); 

Я создал индекс входа на Params поле, как это:

Скажем, у меня есть 3 модели в этой таблице со значениями таких Params:

1. {'param1' : 'value1', 'param2' : 'value2'} 
2. {'param1' : 'value1', 'param2' : 'othervalue'} 
3. {'param3' : 'value3', 'param2' : 'value2'} 

Каждый продукт может иметь только одно значение на e param, но во всей базе данных могут быть N параметров и значений X для каждого из них.

я могу сделать запрос типа, который без проблем:

SELECT * FROM products WHERE params['param1'] = 'value1'; 

Но главный вопрос заключается в том, как я могу сделать запрос, как это:

SELECT * FROM products WHERE params['param1'] = 'value1' AND params['param2'] = 'value2'; 

Теперь я получаю сообщение об ошибке , что предупреждает меня об эффективности:

InvalidRequest: Error from server: code=2200 [Invalid query] message="Cannot execute this query as it might involve data filtering and thus may have unpredictable performance. If you want to execute this query despite the performance unpredictability, use ALLOW FILTERING" 

Я preety new к Cassandra и NoSQL. Я знаю из курсов Datastax, что использование ALLOW FILTERING - последнее, что я должен сделать в Кассандре. Есть ли эффективный способ добиться того, чего я хочу в Кассандре? Может быть, мне следует моделировать это совершенно по-другому? Я буду очень рад за помощь в этой теме.

+0

Да, вы правы для изменения модели, поскольку вы не можете создать таблицу с параметром (столбец типа карты) в качестве первичного ключа или в виде материального представления (типы коллекции не могут быть частью первичного ключа, а также тип счетчика). , поэтому, если вы хотите пропустить «ALLOW FILTERING», вам нужно включить первичный ключ в запрос. –

+1

Коллекции представляют собой небольшие группы данных, которые вы получаете сразу. Если вы хотите получить доступ к кортежам на более тонком уровне и по-прежнему сможете спросить «какие все пары данных для данного ключа», вы должны использовать таблицу следующим образом: CREATE TABLE details ( key TEXT , detail_key text, detail_value text, ПЕРВИЧНЫЙ КЛЮЧ (ключ, detail_key) ); Это позволит SELECT * FROM details WHERE key =? а также SELECT * FROM detail WHERE key =? AND detail_key =?. –

ответ

1

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

create table name_by_param{ 
    param text, 
    value text, 
    uuid text, 
    name text 
    primary key ((param,value),uuid) 
    } 

Пример вставки для продукта - Darthvedar

insert into name_by_param (param,value,uuid,name) values ('birthname','ani','uuid1','darthvedar'); 
    insert into name_by_param (param,value,uuid,name) values ('side','darkside','uuid1','darthvedar'); 
    insert into name_by_param (param,value,uuid,name) values ('age','40','uuid1','darthvedar'); 

пример вставляет для продукта - Оби-Ван-Кеноби

insert into name_by_param (param,value,uuid,name) values ('birthname','O-ben','uuid2','Obi-wan-kenobi'); 
insert into name_by_param (param,value,uuid,name) values ('side','force','uuid2','Obi-wan-kenobi'); 
insert into name_by_param (param,value,uuid,name) values ('age','40','uuid2','Obi-wan-kenobi'); 

Выбор запросов -

select * from name_by_param where token(param,value) = token('birthname','ani') and token(param,value) = token('side','force'); 

Выше запроса должен возвращать две строки, я не пробовал сам, но это работает, надеюсь, это поможет.

+0

Мне очень понравилась эта идея, но кажется, что ее нельзя использовать с оператором равенства: 'param, value не может быть ограничено более чем одним отношением, если оно включает Equal' - i, оно работает, если я изменю его на gt или lt, но это, очевидно, не решило проблему. – clk

+0

Вы пытались «ИЛИ» в запросе thet, например -token (param, value) = токен ('birthname', 'ani') {OR} token (param, value) = токен ('side', 'force'); – Gunwant

+0

Также вы пытаетесь использовать пример оператора IN - токен (..) IN (токен (...), токен (...)) – Gunwant