Cassandraも0.
前回まででデータの投入、
前準備としてデータを投入しておく
検索メソッドの確認の前準備として、
- 郵便番号データのダウンロード:日本郵便
- URL:http://
www. post. japanpost. jp/ zipcode/ dl/ kogaki/ lzh/ 13tokyo. lzh
データは説明のため簡易的なデータ構造とします。
- キーは郵便番号
- データは、
郵便番号 (postalCode)、 あて先 (address)、 あて先読み方 (addressYomi) の3つ - スーパーカラムは使わない
データを投入するコードは以下のとおりです。
Cassandra.Client client = new Cassandra.Client(protocol);
long timestamp = System.currentTimeMillis();
Map<String, Map<String, List<Mutation>>> map = new HashMap<String, Map<String, List<Mutation>>>();
is = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("13TOKYO.CSV");
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "MS932"));
String line = null;
while ((line = reader.readLine()) != null) {
List mutations = new ArrayList();
String[] lines = line.split(",");
String postalCode = removeQuote(lines[2]);
String addressYomi = buildAddressYomi(lines);
String address = buildAddress(lines);
System.out.println(postalCode + " " + addressYomi + " "
+ address);
{
Mutation mutation = new Mutation();
ColumnOrSuperColumn csc = new ColumnOrSuperColumn();
csc.setColumn(new Column("postalCode".getBytes(),
postalCode.getBytes(), timestamp));
mutation.setColumn_or_supercolumn(csc);
mutations.add(mutation);
}
{
Mutation mutation = new Mutation();
ColumnOrSuperColumn csc = new ColumnOrSuperColumn();
csc.setColumn(new Column("address".getBytes(), address
.getBytes(), timestamp));
mutation.setColumn_or_supercolumn(csc);
mutations.add(mutation);
}
{
Mutation mutation = new Mutation();
ColumnOrSuperColumn csc = new ColumnOrSuperColumn();
csc.setColumn(new Column("addressYomi".getBytes(),
addressYomi.getBytes(), timestamp));
mutation.setColumn_or_supercolumn(csc);
mutations.add(mutation);
}
Map<String, List<Mutation>> mutmap = new HashMap<String, List<Mutation>>();
mutmap.put(COLUMN_FAMILY, mutations);
map.put(new String(postalCode), mutmap);
count++;
}
client.batch_mutate(KEYSPACE, map, ConsistencyLevel.ONE);
reader.close();
設定ファイル
<ColumnFamily Name="SimpleAddress" CompareWith="UTF8Type" />
実行してデータを投入します。以下のようになるはずです。
...
1002100 トウキョウト オガサワラムラ 東京都 小笠原村
1002101 トウキョウト オガサワラムラ チチジマ 東京都 小笠原村 父島
1002211 トウキョウト オガサワラムラ ハハジマ 東京都 小笠原村 母島
3654件インサート完了.
このデータをサンプルとして、
単一カラムを取得するには
まずは1件検索してみましょう。Cassandraではgetメソッドを使います。getメソッドは以下のようなAPIになっています。
ColumnOrSuperColumn get(キースペース, キー, ColumnPath, ConsistencyLevel)
コードは以下のようになります。この例では郵便番号
Cassandra.Client client = new Cassandra.Client(protocol);
ColumnPath path = new ColumnPath(COLUMN_FAMILY);
path.setColumn("address".getBytes());//検索するカラム名を指定
ColumnOrSuperColumn csc = client.get(KEYSPACE, "1006528", path,
ConsistencyLevel.ONE);
Column c = csc.getColumn();
String name = new String(c.getName());
String value = new String(c.getValue());
System.out.println(name + " -> " + value + "(" + c.getTimestamp()
+ ")");
結果は以下のようになります。
address -> 東京都 千代田区 丸の内新丸の内ビルディング(28階)(1281276409219)
第5回でも説明したように、
今回のサンプルではありませんが、
ColumnPath path = new ColumnPath(COLUMN_FAMILY);
path.setSuper_column(LongUtil.toByteArray(1006528L));//スーパーカラムを指定
path.setColumn("address".getBytes());//カラム名を指定
また戻り値のColumnOrSuperColumnからデータをどのように取得するかは、
- カラムの場合
- →ColumnOrSuperColumn#getColumn()でカラムを取得
- スーパーカラムの場合
- →ColumnOrSuperColumn#getSuperColumn()#getColumns()でスーパーカラム内のカラムを取得
複数カラムを取得するには
次に1つのキーから複数カラムを同時に取得してみましょう。この場合、
List<ColumnOrSuperColumn> get_slice(キースペース, キー, ColumnParent, SlicePredicate, ConsistencyLevel);
実際のコードは以下のようになります。
Cassandra.Client client = new Cassandra.Client(protocol);
ColumnParent parent = new ColumnParent(COLUMN_FAMILY);
String key = "1006528";
// カラムの指定
SlicePredicate predicate = new SlicePredicate();
predicate.setColumn_names(Arrays.asList("postalCode".getBytes(),
"address".getBytes()));
List<ColumnOrSuperColumn> ret = client.get_slice(KEYSPACE, key,
parent, predicate, ConsistencyLevel.ONE);
// 結果を表示
for (ColumnOrSuperColumn csc : ret) {
Column column = csc.getColumn();
String name = new String(column.getName());
String value = new String(column.getValue());
System.out.println("\t" + name + " -> " + value + "("
+ column.getTimestamp() + ")");
}
結果は以下のとおりです。
address -> 東京都 千代田区 丸の内新丸の内ビルディング(28階)(1281276409219)
postalCode -> 1006528(1281276409219)
ここでColumnParentとSlicePredicateという見慣れないクラスが2つ登場していますね。これらを説明します。
ColumnParent
ColumnParentはColumnPathと非常に似た概念のクラスですが、
- ColumnPath → 単一のカラムを見つけるためのクラス
- ColumnParent→ 複数のカラムを見つけるためのクラス
ColumnParentはディレクトリ構造で言うところの /../ にあたります。ある単一カラムを基点にしてディレクトリ構造をさかのぼり、
ColumnParentは以下の2とおりのどちらかをとります。
- カラムの場合 → カラムファミリのみを指定
- スーパーカラムの場合 → カラムファミリとスーパーカラムを指定
SlicePredicate
SlicePredicateは検索をフィルタするための指定を行うクラスです。フィルタリングにおもに以下の2つの設定ができます。
- ①カラム名による指定
- ②カラム名の範囲による指定
上記のサンプルコードでは、
第4回でかんたんに説明しましたが、
今回は設定ファイルにCompareWithでUTF8を指定しているので、
検索対象のカラムを絞るには
②のカラム名の範囲によって検索対象のカラムを絞ることもできます。この場合はSliceRangeというクラスを使い、
- カラムの開始位置 →SliceRange#setStartで指定
- カラムの終了位置 →SliceRange#setEndで指定
SliceRangeが便利な局面としては、
Cassandraでは日付などをキーとしてデータを入れたり、
注意点としては、
たとえば、
- start → postalCode
- end → addressYomi
SliceRangeを使ったサンプルコードは以下のようになります。結果を比較しやすいように、
Cassandra.Client client = new Cassandra.Client(protocol);
ColumnParent parent = new ColumnParent(COLUMN_FAMILY);
String key = "1006528";
SlicePredicate predicate = new SlicePredicate();
// 項目の中から、addressYomiからpostalCodeまでのレンジに入る項目を抽出.
SliceRange range = new SliceRange();
range.setStart("addressYomi".getBytes());
range.setFinish("postalCode".getBytes());
predicate.setSlice_range(range);
List<ColumnOrSuperColumn> ret = client.get_slice(KEYSPACE, key,
parent, predicate, ConsistencyLevel.ONE);
System.out.println("SliceRangeでカラムを絞った場合");
for (ColumnOrSuperColumn csc : ret) {
Column column = csc.getColumn();
String name = new String(column.getName());
String value = new String(column.getValue());
System.out.println("\t" + name + " -> " + value + "("
+ column.getTimestamp() + ")");
}
System.out.println("SliceRangeでカラムを絞らなかった場合");
SliceRange rangeAll = new SliceRange();
rangeAll.setStart("".getBytes());
rangeAll.setFinish("".getBytes());
predicate.setSlice_range(rangeAll);
ret = client.get_slice(KEYSPACE, key, parent, predicate,
ConsistencyLevel.ONE);
for (ColumnOrSuperColumn csc : ret) {
Column column = csc.getColumn();
String name = new String(column.getName());
String value = new String(column.getValue());
System.out.println("\t" + name + " -> " + value + "("
+ column.getTimestamp() + ")");
}
結果は以下のようになります。
addressYomi -> トウキョウト チヨダク マルノウチシンマルノウチビルディング(28カイ)(1281276409219)
postalCode -> 1006528(1281276409219)
address -> 東京都 千代田区 丸の内新丸の内ビルディング(28階)(1281276409219)
addressYomi -> トウキョウト チヨダク マルノウチシンマルノウチビルディング(28カイ)(1281276409219)
postalCode -> 1006528(1281276409219)
昇順・降順を制御するには
勘の良い方はお気づきかもしれませんが、
そこでSliceRangeにはSliceRange#setReversedというメソッドがついており、
先ほどのコードで降順にしてみましょう。コードは以下のようになります。
SliceRange range = new SliceRange();
range.setStart("postalCode".getBytes());
range.setFinish("addressYomi".getBytes());
range.setReversed(true);
結果は以下のようになります。
postalCode -> 1006528(1281276409219)
addressYomi -> トウキョウト チヨダク マルノウチシンマルノウチビルディング(28カイ)(1281276409219)
postalCode -> 1006528(1281276409219)
addressYomi -> トウキョウト チヨダク マルノウチシンマルノウチビルディング(28カイ)(1281276409219)
address -> 東京都 千代田区 丸の内新丸の内ビルディング(28階)(1281276409219)
今回はgetとget_
Cassandraの検索系メソッドは非常に特徴的で、
次回は、
今回の記事で紹介したサンプルコード全体は以下からダウンロードできます。