前回からずいぶん時間がたってしまいました。申し訳ありません。
前回はgetメソッド、
前回同様、
複数のロウを取得する ~get_range_slicesメソッド
前回は基本的に1つのロウに対する操作でしたが、
まずはコードを見てください。リスト1は郵便番号、
public class SimpleAddressSearchGetRangeSlices {
public static final String KEYSPACE = "Keyspace1";
public static final String COLUMN_FAMILY = "SimpleAddress";
public static void main(String[] args) throws IOException {
TSocket transport = new TSocket("localhost", 9160);
TProtocol protocol = new TBinaryProtocol(transport);
try {
transport.open();
} catch (TTransportException e) {
throw new RuntimeException(e);
}
try {
Cassandra.Client client = new Cassandra.Client(protocol);
SlicePredicate predicate = new SlicePredicate();
predicate.setColumn_names(Arrays.asList("postalCode".getBytes(),
"address".getBytes(), "addressYomi".getBytes()));
KeyRange range = new KeyRange();
range.setStart_key("");
range.setEnd_key("");
List<KeySlice> ret = client.get_range_slices(KEYSPACE,
new ColumnParent(COLUMN_FAMILY), predicate, range,
ConsistencyLevel.ONE);
int i = 0;
for (KeySlice keySlice : ret) {
System.out.println((i++) + " key = " + keySlice.getKey());
for (ColumnOrSuperColumn csc : keySlice.getColumns()) {
Column column = csc.getColumn();
String name = new String(column.getName());
String value = new String(column.getValue());
System.out.println("\t\t" + name + " -> " + value + "("
+ column.getTimestamp() + ")");
}
}
} catch (InvalidRequestException e) {
throw new RuntimeException(e);
} catch (UnavailableException e) {
throw new RuntimeException(e);
} catch (TimedOutException e) {
throw new RuntimeException(e);
} catch (TException e) {
throw new RuntimeException(e);
} finally {
try {
transport.flush();
} catch (TTransportException e) {
throw new RuntimeException(e);
} finally {
transport.close();
}
}
}
}
SlicePredicateについては前回ご紹介しているので、
このコードで新たに登場しているのは、
KeyRange
KeyRangeは複数ロウを取得するときのレンジを表すクラスです。これには以下のようなことを設定でき、
- キーの開始から終了のレンジ
- 取得する最大数
- トークンによるレンジ
リスト1のコードでは、
KeyRange range = new KeyRange();
range.setStart_key("");
range.setEnd_key("");
ちなみに、
KeyRange range = new KeyRange(1000);
range.setStart_key("");
range.setEnd_key("");
また、
KeyRange range = new KeyRange(1000);
range.setStart_key("1760000");
range.setEnd_key("1760004");
このようにキーのレンジを指定できるのですが、
KeySlice
次はKeySliceです。KeySliceはget_
取得するコードは、
for (KeySlice keySlice : ret) {
System.out.println((i++) + " key = " + keySlice.getKey());
for (ColumnOrSuperColumn csc : keySlice.getColumns()) {
Column column = csc.getColumn();
String name = new String(column.getName());
String value = new String(column.getValue());
System.out.println("\t\t" + name + " -> " + value + "("
+ column.getTimestamp() + ")");
}
}
get_range_slicesメソッドで注意すべきところ
ここまでの感じだとCassandraでもレンジクエリが簡単にできている感じがありますが、
Cassandraはデータをノード間に分散させる方式として、
これを使う最大のメリットは、
以下はリスト1を実行した結果です。一目瞭然ですね。キーによる順序が一貫せずに値が返ってきています。
0 key = 1680082
address -> 東京都 杉並区 久我山(1281276409219)
addressYomi -> トウキョウト スギナミク クガヤマ(1281276409219)
postalCode -> 1680082(1281276409219)
1 key = 1780062
address -> 東京都 練馬区 大泉町(1281276409219)
addressYomi -> トウキョウト ネリマク オオイズミマチ(1281276409219)
postalCode -> 1780062(1281276409219)
2 key = 1750081
address -> 東京都 板橋区 新河岸(1281276409219)
addressYomi -> トウキョウト イタバシク シンガシ(1281276409219)
postalCode -> 1750081(1281276409219)
3 key = 1540003
address -> 東京都 世田谷区 野沢(1281276409219)
addressYomi -> トウキョウト セタガヤク ノザワ(1281276409219)
postalCode -> 1540003(1281276409219)
パーティショナクラスを使い分ける
では、
実はCassandraは別の手段を準備してあります。それはOrderPreservingPartitionerというパーティショナを使う方法です。この方法ならば、
ただしメリットの裏にはデメリットもあるものです。OrderPreservingPartitionerを使うと、
そのため、
実行すると、
0 key = 1000000
address -> 東京都 千代田区 (1281196753776)
addressYomi -> トウキョウト チヨダク (1281196753776)
postalCode -> 1000000(1281196753776)
1 key = 1000001
address -> 東京都 千代田区 千代田(1281196753776)
addressYomi -> トウキョウト チヨダク チヨダ(1281196753776)
postalCode -> 1000001(1281196753776)
2 key = 1000002
address -> 東京都 千代田区 皇居外苑(1281196753776)
addressYomi -> トウキョウト チヨダク コウキョガイエン(1281196753776)
postalCode -> 1000002(1281196753776)
3 key = 1000003
address -> 東京都 千代田区 一ツ橋(1丁目)(1281196753776)
addressYomi -> トウキョウト チヨダク ヒトツバシ(1チョウメ)(1281196753776)
postalCode -> 1000003(1281196753776)
RandomPartitionerとOrderPreservingPartitionerのどちらを使うかは、
また、
特定のキーの行を複数取得する ~multiget_sliceメソッド
ある特定キーの集合を取得したいときに使うのがmultiget_
public class SimpleAddressSearchMultiGetSlice {
public static final String KEYSPACE = "Keyspace1";
public static final String COLUMN_FAMILY = "SimpleAddress";
public static void main(String[] args) throws IOException {
TSocket transport = new TSocket("localhost", 9160);
TProtocol protocol = new TBinaryProtocol(transport);
try {
transport.open();
} catch (TTransportException e) {
throw new RuntimeException(e);
}
try {
Cassandra.Client client = new Cassandra.Client(protocol);
SlicePredicate predicate = new SlicePredicate();
predicate.setColumn_names(Arrays.asList("postalCode".getBytes(),
"address".getBytes()));
Map<String, List<ColumnOrSuperColumn>> ret = client.multiget_slice(
KEYSPACE, Arrays.asList("1080074", "1080075"),
new ColumnParent(COLUMN_FAMILY), predicate,
ConsistencyLevel.ONE);
for (Map.Entry<String, List<ColumnOrSuperColumn>> e : ret
.entrySet()) {
String key = e.getKey();
System.out.println("key = " + key);
for (ColumnOrSuperColumn csc : e.getValue()) {
Column c = csc.getColumn();
String name = new String(c.getName());
String value = new String(c.getValue());
System.out.println(name + " -> " + value + "("
+ c.getTimestamp() + ")");
}
System.out.println();
}
} catch (InvalidRequestException e) {
throw new RuntimeException(e);
} catch (UnavailableException e) {
throw new RuntimeException(e);
} catch (TimedOutException e) {
throw new RuntimeException(e);
} catch (TException e) {
throw new RuntimeException(e);
} finally {
try {
transport.flush();
} catch (TTransportException e) {
throw new RuntimeException(e);
} finally {
transport.close();
}
}
}
}
リスト2の例は
という処理を行うものです。
カラム数を取得するには ~get_countメソッド
カラム数を取得するには、
Cassandra.Client client = new Cassandra.Client(protocol);
int count = client.get_count(KEYSPACE, "1500002", new ColumnParent(
COLUMN_FAMILY), ConsistencyLevel.ONE);
今回は、
この中でやはり重要なのが、
今回までは、