デイリーのアクセスを取得
次に、デイリーのアクセスを取得するコードです。取得するColumnFamilyやColumnが違っているくらいで、基本的にはアワリーの場合と変わった部分はありません。
// デイリーのアクセスを取得する
public List<Access> getDailyCount(String domain, String path, Calendar startDay, Calendar endDay) throws IOException {
// Scanの作成
Scan scan;
String reversedDomain = reverseDomain(domain);
if (path != null) {
byte[] row = createRow(reversedDomain, path);
scan = new Scan(row, row);
} else {
byte[] prefix = Bytes.toBytes(reversedDomain);
scan = new Scan(prefix);
scan.setFilter(new PrefixFilter(prefix));
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
// startDayとendDayから取得したいColumnを指定
Calendar cal = (Calendar) startDay.clone();
while (cal.before(endDay)) {
scan.addColumn(DAILY_COLUMN_FAMILY, Bytes.toBytes(sdf.format(cal.getTime())));
cal.add(Calendar.DAY_OF_MONTH, 1);
}
// 結果の取得
List<Access> ret = new ArrayList<Access>();
HTableInterface table = hTablePool.getTable(TABLE);
try {
ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
String[] domainAndPath = extractDomainAndPath(result.getRow());
for (Map.Entry<byte[], byte[]> entry: result.getFamilyMap(DAILY_COLUMN_FAMILY).entrySet()) {
byte[] qualifier = entry.getKey();
byte[] value = entry.getValue();
// 時間
Calendar time = Calendar.getInstance();
time.setTime(sdf.parse(Bytes.toString(qualifier)));
// Accessオブジェクトの作成
Access access = new Access();
access.setTime(time);
access.setDomain(reverseDomain(domainAndPath[0]));
access.setPath(domainAndPath[1]);
access.setCount(Bytes.toLong(value));
ret.add(access);
}
}
} catch (ParseException e) {
// 省略
} finally {
table.close();
}
return ret;
}
トータルのアクセスを取得
最後に、トータルのアクセスを取得するコードです。これも、基本的にはアワリーやデイリーのコードと同様になります。
ただしトータルのアクセスの場合、年月日などの情報がないので、Columnを限定する処理はありません。
// トータルのアクセスを取得する
public List<Access> getTotalCount(String domain, String path) throws IOException {
// Scanの作成
Scan scan;
String reversedDomain = reverseDomain(domain);
if (path != null) {
byte[] row = createRow(reversedDomain, path);
scan = new Scan(row, row);
} else {
byte[] prefix = Bytes.toBytes(reversedDomain);
scan = new Scan(prefix);
scan.setFilter(new PrefixFilter(prefix));
}
scan.addFamily(TOTAL_COLUMN_FAMILY); // ColumnFamilyを限定する
// 結果の取得
List<Access> ret = new ArrayList<Access>();
HTableInterface table = hTablePool.getTable(TABLE);
try {
ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
String[] domainAndPath = extractDomainAndPath(result.getRow());
// Accessオブジェクトの作成
Access access = new Access();
access.setDomain(reverseDomain(domainAndPath[0]));
access.setPath(domainAndPath[1]);
access.setCount(Bytes.toLong(result.getValue(TOTAL_COLUMN_FAMILY, HConstants.EMPTY_BYTE_ARRAY)));
ret.add(access);
}
} finally {
table.close();
}
return ret;
}
まとめ
今回は、HBaseを使って簡易アクセス解析サービスを作成しました。前回に比べて、比較的シンプルで分かりやすかったのではないでしょうか。次回も引き続き、HBaseを使ったアプリケーションの別のケーススタディを紹介する予定です。
また、株式会社サイバーエージェントでは、Hadoop/HBaseエンジニアを募集しています。ご興味のある方はこちらからエントリーしていただければと思います。エンジニア>R&Dエンジニア>R&Dエンジニアを選択しエントリーしていただければ幸いです。
