How do I create table with composite keys using astyanax client. For now I’ve created it with cqlsh -3, and this is how it looks like in cli:
[default@KS] describe my_cf;
ColumnFamily: my_cf
Key Validation Class: org.apache.cassandra.db.marshal.UTF8Type
Default column value validator: org.apache.cassandra.db.marshal.UTF8Type
Columns sorted by: org.apache.cassandra.db.marshal.CompositeType(org.apache.cassandra.db.marshal.TimeUUIDType,org.apache.cassandra.db.marshal.UTF8Type)
GC grace seconds: 864000
Compaction min/max thresholds: 4/32
Read repair chance: 0.1
DC Local Read repair chance: 0.0
Replicate on write: true
Caching: KEYS_ONLY
Bloom Filter FP chance: default
Built indexes: []
Compaction Strategy: org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy
Compression Options:
sstable_compression: org.apache.cassandra.io.compress.SnappyCompressor
This is how I would expect it to be in cqlsh:
CREATE TABLE my_cf (
... key text,
... timeid timeuuid,
... flag boolean,
... data text,
... PRIMARY KEY (key, timeid));
I got it working with composite key stored as a blob which is a problem.
my code
public class MyKey {
@Component(ordinal=0)
private String key;
@Component(ordinal=1)
private UUID timeid;
//...
}
CF
public static ColumnFamily<MyKey, String> MY_CF = ColumnFamily
.newColumnFamily("my_cf",
new AnnotatedCompositeSerializer<MyKey>(MyKey.class),
StringSerializer.get());
KS
ksDef = cluster.makeKeyspaceDefinition();
ksDef.setName(keyspaceName)
.setStrategyOptions(keyspaceOptions)
.setStrategyClass("SimpleStrategy")
.addColumnFamily(
cluster.makeColumnFamilyDefinition()
.setName(MY_CF.getName())
.setComparatorType("UTF8Type")
.setDefaultValidationClass("UTF8Type")
// blob if no key validation class specified
// and something looking as a string if I use this: .setKeyValidationClass("CompositeType(UTF8Type, TimeUUIDType)")
// anyway there's a single column per composite key
.addColumnDefinition(
cluster.makeColumnDefinition()
.setName("flag")
.setValidationClass(
"BooleanType"))
.addColumnDefinition(
cluster.makeColumnDefinition()
.setName("data")
.setValidationClass(
"UTF8Type")));
cluster.addKeyspace(ksDef);
mutation
MutationBatch m = ks.prepareMutationBatch();
for (char keyName = 'A'; keyName <= 'C'; keyName++) {
MyKey myKey = new MyKey("THEKEY_" + keyName, TimeUUIDUtils.getUniqueTimeUUIDinMillis());
ColumnListMutation<String> cfm = m.withRow(MY_CF, myKey);
cfm.putColumn("flag", true, null);
cfm.putColumn("data", "DATA_" + keyName, null);
}
m.execute();
cqlsh:KS>describe columnfamily my_cf;
CREATE TABLE my_cf (
KEY blob PRIMARY KEY,
flag boolean,
data text
) WITH ...
cqlsh:KS>select * from my_cf;
key | flag | data
----------------------------------------------------------+--------+---------
00064953494e5f420000109f4513d0e3ac11e19c400022191ad62b00 | True | DATA_B
cqlsh:KS> select * from my_cf where key = ‘THEKEY_B’ order by timeid desc;
Bad Request: Order by on unknown column timeid
doesnt’ it look right in cassandra-cli below? why it doesn’t work in cqlsh?
cassandra-cli] list my_cf;
RowKey: THEKEY_B:09f29941-e3c2-11e1-a7ef-0022191ad62b
=> (column=active, value=true, timestamp=1344695832788000)
=> (column=data, value=DATA_B, timestamp=1344695832788000)
What am I doing wrong?
(astyanax 1.0.6, cassandra 1.1.2)
cqlsh>[cqlsh 2.2.0 | Cassandra 1.1.2 | CQL spec 3.0.0 | Thrift protocol 19.32.0]
From what I’ve been able to figure out, composite primary keys
represent a major divergence in the protocol and interface to
cassandra and the protocol you use controls the features you have
access to.
For instance, astyanax and hector are primarily thrift protocol
clients, while CQL, more than just a language, is (or will be?) a binary protocol.
The two protocols are not equivalent and CQL3 with composite primary
keys makes things very different.
The thing to understand about “TABLES” with composite primary keys is that they
essentially translate into wide rows with composite column names. The
first part of the primary key is the row key and the remaining parts
are used as a prefix along with the TABLE-column name as the column name in
the wide row.
In your instance, the row key is “key” and the column prefix is
“timeid”, so the flag field of what you are inserting is actually a
column named :flag and data is :data and so
on.
In order for this to work, the CQL protocol interface to cassandra is
converting “TABLES” into wide rows and transparently handling all of
that column naming.
The thrift interface doesn’t take care of this stuff and and when you
do a mutation, it just writes columns like it is used to, without the
virtual addressing.
So, in fact, the results do not look right in your cassandra-cli. If you do an insert from cqlsh -3, here is what it should look like from the cassandra-cli point of view (with a simple text date):
CQL3 and tables look really attractive, but there are some trade-offs to be made and there doesn't seem to be solid java client support yet.