使用Cassandra中的hector客户端使用组合键的第一个组件获取行

时间:2013-10-15 05:53:22

标签: java java-ee cassandra hector

我在rowkey中使用复合数据类型,列族如下所示

create column family CompositeTest
with comparator = 'UTF8Type'
and key_validation_class = 'CompositeType(UTF8Type,UTF8Type)'
and default_validation_class = 'UTF8Type';

此列系列的样本数据如下,

RowKey: s2:2222222
=> (column=param1, value=value1
=> (column=param2, value=value2
=> (column=param3, value=value3
-------------------
RowKey: s2:3333333
=> (column=param1, value=value1
=> (column=param2, value=value2
=> (column=param3, value=value3
-------------------
RowKey: s2:1111111
=> (column=param1, value=value1
=> (column=param2, value=value2
=> (column=param3, value=value3
-------------------
RowKey: s1:3333333
=> (column=param1, value=value1
=> (column=param2, value=value2
=> (column=param3, value=value3
-------------------
RowKey: s1:2222222
=> (column=param1, value=value1
=> (column=param2, value=value2
=> (column=param3, value=value3
-------------------
RowKey: s1:1111111
=> (column=param1, value=value1
=> (column=param2, value=value2
=> (column=param3, value=value3

我想获得行键的第一个组件为“s1”的所有行。是否可以使用Hector客户端?如果不是那么cassandra客户端可能吗?

我尝试使用以下代码,但它不起作用,

Composite start = new Composite();
        start.addComponent(0, "s1", ComponentEquality.EQUAL);

        Composite end = new Composite();
        end.addComponent(0, "s1", ComponentEquality.GREATER_THAN_EQUAL);

        RangeSlicesQuery<Composite, String, String> rangeSlicesQuery = HFactory.createRangeSlicesQuery(keyspace, new CompositeSerializer(), StringSerializer.get(),  StringSerializer.get()); 
        rangeSlicesQuery.setKeys(start, end);
        rangeSlicesQuery.setRange("param1", "param3", false, 100);
        rangeSlicesQuery.setColumnFamily("CompositeTest");
        rangeSlicesQuery.setRowCount(11);
        QueryResult<OrderedRows<Composite, String, String>>  queryResult = rangeSlicesQuery.execute();

        Rows<Composite, String, String> rows = queryResult.get();
        Iterator<Row<Composite, String, String>> rowsIterator = rows.iterator();

提前致谢...

2 个答案:

答案 0 :(得分:2)

这在Cassandra使用任何客户端都是不可能的。虽然行键显示为复合对象,但应用程序开发人员在Cassandra本身中的行键是一个单数字节数组,它作为单个原子值存储在Cassandra的SSTable中。

意思是,您只能使用整个密钥 查询行,而不仅仅是密钥的一部分。否则,您必须扫描整个列族,直到找到匹配为止 - 这将非常昂贵。

话虽如此,如果您确实需要能够仅使用部分行键来查询列族中的行,那么我强烈建议为这些关键部分创建单独的索引列族。这将允许您使用标准键/列查找来查找原始数据列系列中符合条件的所有行。

答案 1 :(得分:1)

问题是您正在尝试对行键执行切片。 如果您在Cassandra中使用随机分区器(例如RandomPartitioner或Murmur3Partitioner),则根本不可能。如果您使用订单保留分区程序,则可能(但我从未尝试过)。在你的情况下,应该是一个不幸的CompositeKeyPartitioner,因此你应该自己编写它。然后,您还应该根据数据计算正确的令牌来配置群集。 如您所见,这不是最简单的方法。

但是,如果只是将复合值放在列名而不是键中,则可以这样做。 您可以通过以下方式定义CF:

create column family CompositeTest
   with comparator = 'CompositeType(UTF8Type,UTF8Type)'
   and key_validation_class = 'UTF8Type'
   and default_validation_class = 'UTF8Type';

并存储数据:

RowKey: s2
=> (column=2222222:param1, value=value1
=> (column=2222222:param2, value=value2
=> (column=2222222:param3, value=value3
=> (column=3333333:param1, value=value1
=> (column=3333333:param2, value=value2
=> (column=3333333:param3, value=value3
=> (column=1111111:param1, value=value1
=> (column=1111111:param2, value=value2
=> (column=1111111:param3, value=value3
-------------------
RowKey: s1:
=> (column=3333333:param1, value=value1
=> (column=3333333:param2, value=value2
=> (column=3333333:param3, value=value3
=> (column=2222222:param1, value=value1
=> (column=2222222:param2, value=value2
=> (column=2222222:param3, value=value3
=> (column=1111111:param1, value=value1
=> (column=1111111:param2, value=value2
=> (column=1111111:param3, value=value3

使用此结构,您认为查询非常简单,然后您可以始终对列名称进行切片,以便仅选择所需间隔内的列。