2015-02-02 11 views
9

Sono nuovo a Cassandra. Ho riscontrato un problema in CQL IN query, se la tabella ha la colonna Tipo SET funziona.Cassandra IN query non funziona se la tabella ha colonna tipo SET

CREATE TABLE test (
    test_date bigint, 
    test_id bigint, 
    caption text, 
    PRIMARY KEY(test_date,test_id) 
); 

select * from test where test_date = 2022015 and test_id IN (1,2); 

ma se aggiungo tag Set al precedente allora si dà errore

CREATE TABLE test1 (
    test_date bigint, 
    test_id bigint, 
    tags set<text>, 
    caption text, 
    PRIMARY KEY(test_date,test_id) 
); 

select * from test1 where test_date = 2022015 and test_id IN (1,2); 

codice = 2200 [Query non valida] message = "Impossibile limitare colonna "test_id" di in relazione come raccolta viene selezionata dalla query "

risposta

2

Non sono sicuro del motivo per cui questa restrizione si deve applicare in particolare per il collec zioni. Ma nel tuo caso è possibile aggirare questo problema, rendendo la parte test_id della vostra chiave di partizione:

PRIMARY KEY((test_date,test_id))

Questo vi permetterà di fare nelle query finché si specifica la prima parte della chiave composta (data del test).

+0

di solito non è una buona idea usare nella dichiarazione con la chiave di partizione. – k0ner

2

Penso che questo errore sia dovuto al modello di archiviazione sottostante di Cassandra. Quando mi interrogo tuo test1 tavolo entro CQLSH (con i miei dati di test), questo è quello che vedo:

[email protected]:stackoverflow> SELECT * FROM test1; 

test_date | test_id | caption | tags 
-----------+---------+-----------+------------------------- 
    2022015 |  1 | blah blah | {'one', 'three', 'two'} 
    2022015 |  2 | blah blah | {'one', 'three', 'two'} 

(2 rows) 

Questo punto di vista dà un'interpretazione fuorviante di come i dati vengono memorizzati in realtà. Questo è quello che sembra quando interrogo stesso tavolo dall'interno cassandra-cli:

[[email protected]] list test1; 
Using default limit of 100 
Using default cell limit of 100 
------------------- 
RowKey: 2022015 
=> (name=1:, value=, timestamp=1422895168730184) 
=> (name=1:caption, value=626c616820626c6168, timestamp=1422895168730184) 
=> (name=1:tags:6f6e65, value=, timestamp=1422895168730184) 
=> (name=1:tags:7468726565, value=, timestamp=1422895168730184) 
=> (name=1:tags:74776f, value=, timestamp=1422895168730184) 
=> (name=2:, value=, timestamp=1422895161891116) 
=> (name=2:caption, value=626c616820626c6168, timestamp=1422895161891116) 
=> (name=2:tags:6f6e65, value=, timestamp=1422895161891116) 
=> (name=2:tags:7468726565, value=, timestamp=1422895161891116) 
=> (name=2:tags:74776f, value=, timestamp=1422895161891116) 

1 Row Returned. 

Ciò suggerisce che i valori Collection (set) sono memorizzati come tasti di colonna aggiuntiva. Una restrizione sull'uso della relazione IN è che deve operare sull'ultima chiave (partizionamento o clustering) di una chiave primaria. Quindi immagino che questa sia una limitazione basata su come Cassandra memorizza i dati della collezione "sotto il cofano".

E solo un avviso, ma l'utilizzo di IN per le query a livello di produzione non è consigliato. Alcuni sono addirittura arrivati ​​alla lista degli anti-pattern di Cassandra. La mia risposta a questa domanda (Is the IN relation in Cassandra bad for queries?) spiega perché le query IN non sono ottimali.

EDIT

Solo per vedere, ho provato lo schema con un elenco invece di un set per vedere se che ha fatto alcuna differenza. Non funzionava ancora, ma dall'interno del cassandra-cli sembrava aggiungere un ulteriore identificatore UUID alla chiave e memorizzare il valore attuale come valore della colonna. Che è diverso da come è stato trattato un set ... questo deve essere il modo in cui i set sono limitati a valori univoci.

0

È possibile utilizzare una vista materializzata con test_id come una parte di partizionamento espressione per soddisfare la vostra richiesta se cambiando il PK sulla vostra tabella di base non è un'opzione:

CREATE MATERIALIZED VIEW test1_mv AS 
SELECT * FROM test1 
WHERE test_date IS NOT NULL AND test_id IS NOT NULL 
PRIMARY KEY((test_date,test_id)); 

quindi utilizzare il vista materializzata al posto del tabella di base nella query:

select * from test1_mv where test_date = 2022015 and test_id IN (1,2); 
Problemi correlati