我是Cassandra的新手。我在CQL IN query
中遇到了一个问题,如果表格有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);
但如果我在上面添加标签设置,则会出错
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);
code = 2200 [无效查询] message =“无法限制列”test_id“ 作为集合的IN关系由查询“
选择
答案 0 :(得分:3)
我不确定为什么这种限制特别适用于收藏品。但在您的情况下,您可以通过将test_id作为分区键的一部分来解决此问题:
PRIMARY KEY((test_date,test_id))
只要您指定复合键的第一部分(test_date),这将允许您执行IN查询。
答案 1 :(得分:3)
我认为你看到这个错误是由于Cassandra的底层存储模型。当我在CQLSH中查询你的test1
表(使用我自己的测试数据)时,这就是我所看到的:
aploetz@cqlsh: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)
此视图对数据的实际存储方式提供了误导性解释。当我从cassandra-cli中查询同一个表时,这就是它的样子:
[default@stackoverflow] 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.
这表明集合(集)值存储为附加列键。使用IN
关系的限制是它必须在主键的最后一个键(分区或聚类)上运行。所以我猜这是一个基于Cassandra如何“隐藏”收集数据的限制。
只是一个警告,但不建议使用IN
进行生产级查询。有些人甚至将其列入Cassandra反模式列表。我对此问题的回答(Is the IN relation in Cassandra bad for queries?)解释了为什么IN
查询不是最优的。
修改强>
只是为了看,我尝试使用列表而不是集合来构建模式,看看是否有任何区别。它仍然不起作用,但是从cassandra-cli中它似乎向键添加了一个额外的UUID标识符,并将实际值存储为列值。这与集合的处理方式不同......这必须是集合如何限制为唯一值。
答案 2 :(得分:0)
如果更改基表上的PK不是一个选项,您可以使用带有test_id的物化视图作为分区表达式的一部分来满足您的要求:
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));
然后在查询中使用物化视图而不是基表:
select * from test1_mv where test_date = 2022015 and test_id IN (1,2);