とりあえず、こちらを参考に
http://wiki.apache.org/cassandra/ClientExamples
Groovyで書いてみました。
お題は、AmazonでのCassandra関連の本の情報に変えてあります。
対象のキースペースとカラムファミリーの情報は、いたって普通です。
[default@Bookshelf] describe Bookshelf; WARNING: CQL3 tables are intentionally omitted from 'describe' output. See https://issues.apache.org/jira/browse/CASSANDRA-4377 for details. Keyspace: Bookshelf: Replication Strategy: org.apache.cassandra.locator.SimpleStrategy Durable Writes: true Options: [replication_factor:1] Column Families: ColumnFamily: Books 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.UTF8Type GC grace seconds: 864000 Compaction min/max thresholds: 4/32 Read repair chance: 0.1 DC Local Read repair chance: 0.0 Populate IO Cache on flush: false 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
サンプルコードは、こちら。
getting_started.groovy
import java.nio.ByteBuffer @Grab('org.apache.cassandra:cassandra-all:1.2.4') import org.apache.cassandra.thrift.Cassandra import org.apache.cassandra.thrift.Column import org.apache.cassandra.thrift.ColumnOrSuperColumn import org.apache.cassandra.thrift.ColumnParent import org.apache.cassandra.thrift.ConsistencyLevel import org.apache.cassandra.thrift.KeyRange import org.apache.cassandra.thrift.KeySlice import org.apache.cassandra.thrift.SlicePredicate import org.apache.cassandra.thrift.SliceRange import org.apache.thrift.transport.TTransport import org.apache.thrift.transport.TFramedTransport import org.apache.thrift.transport.TSocket import org.apache.thrift.protocol.TProtocol import org.apache.thrift.protocol.TBinaryProtocol def transport = new TFramedTransport(new TSocket('localhost', 9160)) def protocol = new TBinaryProtocol(transport) def client = new Cassandra.Client(protocol) transport.open() try { def keyspaceName = 'Bookshelf' def columnFamilyName = 'Books' client.set_keyspace(keyspaceName) def timestamp = System.currentTimeMillis() // 1冊目登録 def id1 = '1' def isbnColumn1 = new Column(ByteBuffer.wrap('isbn'.getBytes('UTF-8'))) isbnColumn1.setValue(ByteBuffer.wrap('978-4873115290'.getBytes('UTF-8'))) isbnColumn1.setTimestamp(timestamp) def nameColumn1 = new Column(ByteBuffer.wrap('name'.getBytes('UTF-8'))) nameColumn1.setValue(ByteBuffer.wrap('Cassandra'.getBytes('UTF-8'))) nameColumn1.setTimestamp(timestamp) def priceColumn1 = new Column(ByteBuffer.wrap('price'.getBytes('UTF-8'))) priceColumn1.setValue(ByteBuffer.wrap('3570'.getBytes('UTF-8'))) priceColumn1.setTimestamp(timestamp) def columnParent = new ColumnParent(columnFamilyName) client.insert(ByteBuffer.wrap(id1.getBytes('UTF-8')), columnParent, isbnColumn1, ConsistencyLevel.ALL) client.insert(ByteBuffer.wrap(id1.getBytes('UTF-8')), columnParent, nameColumn1, ConsistencyLevel.ALL) client.insert(ByteBuffer.wrap(id1.getBytes('UTF-8')), columnParent, priceColumn1, ConsistencyLevel.ALL) // 2冊目登録 def id2 = '2' def isbnColumn2 = new Column(ByteBuffer.wrap('isbn'.getBytes('UTF-8'))) isbnColumn2.setValue(ByteBuffer.wrap('978-4798128436'.getBytes('UTF-8'))) isbnColumn2.setTimestamp(timestamp) def nameColumn2 = new Column(ByteBuffer.wrap('name'.getBytes('UTF-8'))) nameColumn2.setValue(ByteBuffer.wrap('Cassandra実用システムインテグレーション'.getBytes('UTF-8'))) nameColumn2.setTimestamp(timestamp) def priceColumn2 = new Column(ByteBuffer.wrap('price'.getBytes('UTF-8'))) priceColumn2.setValue(ByteBuffer.wrap('3360'.getBytes('UTF-8'))) priceColumn2.setTimestamp(timestamp) def columnParent2 = new ColumnParent(columnFamilyName) client.insert(ByteBuffer.wrap(id2.getBytes('UTF-8')), columnParent, isbnColumn2, ConsistencyLevel.ALL) client.insert(ByteBuffer.wrap(id2.getBytes('UTF-8')), columnParent, nameColumn2, ConsistencyLevel.ALL) client.insert(ByteBuffer.wrap(id2.getBytes('UTF-8')), columnParent, priceColumn2, ConsistencyLevel.ALL) // カラムを、キー指定で取得 def predicate = new SlicePredicate() predicate.setSlice_range( new SliceRange( ByteBuffer.wrap(new byte[0]), ByteBuffer.wrap(new byte[0]), false, 100)) def columnByKey1 = client.get_slice(ByteBuffer.wrap(id1.getBytes()), columnParent, predicate, ConsistencyLevel.ALL); println("columnByKey1 => " + columnByKey1) def columnByKey2 = client.get_slice(ByteBuffer.wrap(id2.getBytes()), columnParent, predicate, ConsistencyLevel.ALL); println("columnByKey2 => " + columnByKey2) // 全キーを取得 def keyRange = new KeyRange(100) keyRange.setStart_key(new byte[0]) keyRange.setEnd_key(new byte[0]) def keySlices = client.get_range_slices(columnParent, predicate, keyRange, ConsistencyLevel.ONE) println("size => " + keySlices.size()) println("keySlices => " + keySlices) for (KeySlice ks : keySlices) { println("keySlice => " + new String(ks.getKey())) } } finally { transport.close() }
Groovyとはいえ、変数宣言の型を書いてない以外は、極力Javaっぽい書き方にしてあります。setterとかも普通に使ってますし。
それにしても、ByteBuffer使いまくり。バイト値に近いところでプログラミングしてる感満載ですね。
依存関係の解決は、
@Grab('org.apache.cassandra:cassandra-all:1.2.4')
だけでなんとかなるみたいです。もっといろいろやらなくちゃいけないかと思いましたけど、これだけでいいのか…。
その他、Javadocが最初見つからなくて、Cassandraのバイナリディストリビューションの中に入っているのにオライリー本を読んでいて気付きました。

- 作者: Eben Hewitt,大谷晋平,小林隆
- 出版社/メーカー: オライリージャパン
- 発売日: 2011/12/24
- メディア: 大型本
- 購入: 1人 クリック: 170回
- この商品を含むブログ (7件) を見る
実行すると、SLF4Jの警告が出るものの一応動作します。
$ groovy getting_started.groovy SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. columnByKey1 => [ColumnOrSuperColumn(column:Column(name:80 01 00 02 00 00 00 09 67 65 74 5F 73 6C 69 63 65 00 00 00 08 0F 00 00 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E, value:80 01 00 02 00 00 00 09 67 65 74 5F 73 6C 69 63 65 00 00 00 08 0F 00 00 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 38 37 33 31 31 35 32 39 30, timestamp:1366554767965)), ColumnOrSuperColumn(column:Column(name:80 01 00 02 00 00 00 09 67 65 74 5F 73 6C 69 63 65 00 00 00 08 0F 00 00 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 38 37 33 31 31 35 32 39 30 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65, value:80 01 00 02 00 00 00 09 67 65 74 5F 73 6C 69 63 65 00 00 00 08 0F 00 00 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 38 37 33 31 31 35 32 39 30 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65 0B 00 02 00 00 00 09 43 61 73 73 61 6E 64 72 61, timestamp:1366554767965)), ColumnOrSuperColumn(column:Column(name:80 01 00 02 00 00 00 09 67 65 74 5F 73 6C 69 63 65 00 00 00 08 0F 00 00 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 38 37 33 31 31 35 32 39 30 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65 0B 00 02 00 00 00 09 43 61 73 73 61 6E 64 72 61 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00..., value:80 01 00 02 00 00 00 09 67 65 74 5F 73 6C 69 63 65 00 00 00 08 0F 00 00 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 38 37 33 31 31 35 32 39 30 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65 0B 00 02 00 00 00 09 43 61 73 73 61 6E 64 72 61 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00..., timestamp:1366554767965))] columnByKey2 => [ColumnOrSuperColumn(column:Column(name:80 01 00 02 00 00 00 09 67 65 74 5F 73 6C 69 63 65 00 00 00 09 0F 00 00 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E, value:80 01 00 02 00 00 00 09 67 65 74 5F 73 6C 69 63 65 00 00 00 09 0F 00 00 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 37 39 38 31 32 38 34 33 36, timestamp:1366554767965)), ColumnOrSuperColumn(column:Column(name:80 01 00 02 00 00 00 09 67 65 74 5F 73 6C 69 63 65 00 00 00 09 0F 00 00 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 37 39 38 31 32 38 34 33 36 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65, value:80 01 00 02 00 00 00 09 67 65 74 5F 73 6C 69 63 65 00 00 00 09 0F 00 00 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 37 39 38 31 32 38 34 33 36 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65 0B 00 02 00 00 00 36 43 61 73 73 61 6E 64 72 61 E5 AE 9F E7 94 A8 E3 82 B7 E3 82 B9 E3 83 86 E3 83 A0 E3 82 A4..., timestamp:1366554767965)), ColumnOrSuperColumn(column:Column(name:80 01 00 02 00 00 00 09 67 65 74 5F 73 6C 69 63 65 00 00 00 09 0F 00 00 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 37 39 38 31 32 38 34 33 36 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65 0B 00 02 00 00 00 36 43 61 73 73 61 6E 64 72 61 E5 AE 9F E7 94 A8 E3 82 B7 E3 82 B9 E3 83 86 E3 83 A0 E3 82 A4..., value:80 01 00 02 00 00 00 09 67 65 74 5F 73 6C 69 63 65 00 00 00 09 0F 00 00 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 37 39 38 31 32 38 34 33 36 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65 0B 00 02 00 00 00 36 43 61 73 73 61 6E 64 72 61 E5 AE 9F E7 94 A8 E3 82 B7 E3 82 B9 E3 83 86 E3 83 A0 E3 82 A4..., timestamp:1366554767965))] size => 2 keySlices => [KeySlice(key:80 01 00 02 00 00 00 10 67 65 74 5F 72 61 6E 67 65 5F 73 6C 69 63 65 73 00 00 00 0A 0F 00 00 0C 00 00 00 02 0B 00 01 00 00 00 01 32, columns:[ColumnOrSuperColumn(column:Column(name:80 01 00 02 00 00 00 10 67 65 74 5F 72 61 6E 67 65 5F 73 6C 69 63 65 73 00 00 00 0A 0F 00 00 0C 00 00 00 02 0B 00 01 00 00 00 01 32 0F 00 02 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E, value:80 01 00 02 00 00 00 10 67 65 74 5F 72 61 6E 67 65 5F 73 6C 69 63 65 73 00 00 00 0A 0F 00 00 0C 00 00 00 02 0B 00 01 00 00 00 01 32 0F 00 02 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 37 39 38 31 32 38 34 33 36, timestamp:1366554767965)), ColumnOrSuperColumn(column:Column(name:80 01 00 02 00 00 00 10 67 65 74 5F 72 61 6E 67 65 5F 73 6C 69 63 65 73 00 00 00 0A 0F 00 00 0C 00 00 00 02 0B 00 01 00 00 00 01 32 0F 00 02 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 37 39 38 31 32 38 34 33 36 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65, value:80 01 00 02 00 00 00 10 67 65 74 5F 72 61 6E 67 65 5F 73 6C 69 63 65 73 00 00 00 0A 0F 00 00 0C 00 00 00 02 0B 00 01 00 00 00 01 32 0F 00 02 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 37 39 38 31 32 38 34 33 36 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65 0B 00 02 00 00 00 36 43 61 73 73 61 6E 64..., timestamp:1366554767965)), ColumnOrSuperColumn(column:Column(name:80 01 00 02 00 00 00 10 67 65 74 5F 72 61 6E 67 65 5F 73 6C 69 63 65 73 00 00 00 0A 0F 00 00 0C 00 00 00 02 0B 00 01 00 00 00 01 32 0F 00 02 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 37 39 38 31 32 38 34 33 36 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65 0B 00 02 00 00 00 36 43 61 73 73 61 6E 64..., value:80 01 00 02 00 00 00 10 67 65 74 5F 72 61 6E 67 65 5F 73 6C 69 63 65 73 00 00 00 0A 0F 00 00 0C 00 00 00 02 0B 00 01 00 00 00 01 32 0F 00 02 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 37 39 38 31 32 38 34 33 36 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65 0B 00 02 00 00 00 36 43 61 73 73 61 6E 64..., timestamp:1366554767965))]), KeySlice(key:80 01 00 02 00 00 00 10 67 65 74 5F 72 61 6E 67 65 5F 73 6C 69 63 65 73 00 00 00 0A 0F 00 00 0C 00 00 00 02 0B 00 01 00 00 00 01 32 0F 00 02 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 37 39 38 31 32 38 34 33 36 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65 0B 00 02 00 00 00 36 43 61 73 73 61 6E 64..., columns:[ColumnOrSuperColumn(column:Column(name:80 01 00 02 00 00 00 10 67 65 74 5F 72 61 6E 67 65 5F 73 6C 69 63 65 73 00 00 00 0A 0F 00 00 0C 00 00 00 02 0B 00 01 00 00 00 01 32 0F 00 02 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 37 39 38 31 32 38 34 33 36 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65 0B 00 02 00 00 00 36 43 61 73 73 61 6E 64..., value:80 01 00 02 00 00 00 10 67 65 74 5F 72 61 6E 67 65 5F 73 6C 69 63 65 73 00 00 00 0A 0F 00 00 0C 00 00 00 02 0B 00 01 00 00 00 01 32 0F 00 02 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 37 39 38 31 32 38 34 33 36 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65 0B 00 02 00 00 00 36 43 61 73 73 61 6E 64..., timestamp:1366554767965)), ColumnOrSuperColumn(column:Column(name:80 01 00 02 00 00 00 10 67 65 74 5F 72 61 6E 67 65 5F 73 6C 69 63 65 73 00 00 00 0A 0F 00 00 0C 00 00 00 02 0B 00 01 00 00 00 01 32 0F 00 02 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 37 39 38 31 32 38 34 33 36 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65 0B 00 02 00 00 00 36 43 61 73 73 61 6E 64..., value:80 01 00 02 00 00 00 10 67 65 74 5F 72 61 6E 67 65 5F 73 6C 69 63 65 73 00 00 00 0A 0F 00 00 0C 00 00 00 02 0B 00 01 00 00 00 01 32 0F 00 02 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 37 39 38 31 32 38 34 33 36 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65 0B 00 02 00 00 00 36 43 61 73 73 61 6E 64..., timestamp:1366554767965)), ColumnOrSuperColumn(column:Column(name:80 01 00 02 00 00 00 10 67 65 74 5F 72 61 6E 67 65 5F 73 6C 69 63 65 73 00 00 00 0A 0F 00 00 0C 00 00 00 02 0B 00 01 00 00 00 01 32 0F 00 02 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 37 39 38 31 32 38 34 33 36 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65 0B 00 02 00 00 00 36 43 61 73 73 61 6E 64..., value:80 01 00 02 00 00 00 10 67 65 74 5F 72 61 6E 67 65 5F 73 6C 69 63 65 73 00 00 00 0A 0F 00 00 0C 00 00 00 02 0B 00 01 00 00 00 01 32 0F 00 02 0C 00 00 00 03 0C 00 01 0B 00 01 00 00 00 04 69 73 62 6E 0B 00 02 00 00 00 0E 39 37 38 2D 34 37 39 38 31 32 38 34 33 36 0A 00 03 00 00 01 3E 2D 02 F2 5D 00 00 0C 00 01 0B 00 01 00 00 00 04 6E 61 6D 65 0B 00 02 00 00 00 36 43 61 73 73 61 6E 64..., timestamp:1366554767965))])] keySlice => 2 keySlice => 1
toStringしただけだと、取れる値がすごいことに…。
cassandra-cliでも見てみます。
[default@Bookshelf] list Books; Using default limit of 100 Using default column limit of 100 ------------------- RowKey: 2 => (column=isbn, value=978-4798128436, timestamp=1366554767965) => (column=name, value=Cassandra実用システムインテグレーション, timestamp=1366554767965) => (column=price, value=3360, timestamp=1366554767965) ------------------- RowKey: 1 => (column=isbn, value=978-4873115290, timestamp=1366554767965) => (column=name, value=Cassandra, timestamp=1366554767965) => (column=price, value=3570, timestamp=1366554767965) 2 Rows Returned. Elapsed time: 8.45 msec(s).
ちゃんと入ってますね。
Thriftを使ったAPIはちゃんと追っかけられていないので、また今度見ます。