
TreasureDataを使っている人は、正直マイノリティであることも理解できますが、
比較的便利にデータベースアクセスができて値を取り出せるプログラムを作ったので、
便利に使ってくれる人もいるのではないかと思い、ブログで公開しておきます。
ニーズがあるようなら、Githubでライブラリ化して公開したいと思います。
ソースコード
get_treasure_data.php
<?php
class Td{
var $datas = [];
var $time = null;
var $api_key = null;
var $sleep_sec = 5;
var $domain = null;
function __construct($options=[]){
$query = @$options["query"];
if(!$query){
die("Error ! Not query.".PHP_EOL);
}
$this->api_key = @$options["api_key"];
if(!$this->api_key){
die("Error ! Not api_key.".PHP_EOL);
}
$this->domain = @$options["domain"];
if(!$this->domain){
die("Error ! Not domain.".PHP_EOL);
}
if($options["sleep_sec"]){
$this->sleep_sec = $options["sleep_sec"];
}
$start_time = microtime(true);
// get job_id
echo PHP_EOL;
echo "1. make_job".PHP_EOL;
$td_job = $this->make_job("production", $query);
// print_r($td_job);
echo "- job_id : ".$td_job["job_id"]. PHP_EOL;
$job_id = $td_job["job_id"];
// get status
echo "2. get status".PHP_EOL;
$status = "running";
while($status === "running"){
$td_status = $this->get_status($job_id);
$status = $td_status["status"];
echo "*";
if($status === "success"){
echo PHP_EOL;
break;
}
else if($status === "running"){
sleep($this->sleep_sec);
}
else{
die("Error : not status.".PHP_EOL);
break;
}
}
// get query result
echo "3. get query result".PHP_EOL;
$this->datas = $this->get_job_result($job_id);
$this->combine_result_data($job_id);
$this->time = microtime(true) - $start_time;
echo PHP_EOL;
}
function kill_job(){
if(!$database){return;}
$cmd = <<<__CMD__
curl -s -i -X POST \
'https://{$this->domain}/v3/job/kill/{$this->job_id}' \
-H 'Authorization: TD1 {$this->api_key}'
__CMD__;
$this->curls[] = $cmd;
exec($cmd, $res);
return $res;
}
function make_job($database=null, $query=null){
if(!$database || !$query){return null;}
$query = str_replace("\r\n" , "\n", $query);
$query = str_replace("\n" , " \\\n", $query);
$query = str_replace('"' , "'", $query);
$cmd = <<<__CMD__
curl -sX POST "https://{$this->domain}/v3/job/issue/presto/{$database}?format=json" \
-H "Authorization: TD1 {$this->api_key}" \
-d query="{$query}"
__CMD__;
exec($cmd , $res);
if($res){
return json_decode($res[0] , true);
}
else{
return null;
}
}
function get_status($job_id=null){
if(!$job_id){return [];}
$cmd = <<<__CMD__
curl -s --location --request GET "https://{$this->domain}/v3/job/status/{$job_id}?format=json" \
--header "Authorization: TD1 {$this->api_key}"
__CMD__;
exec($cmd, $res);
if($res){
return json_decode($res[0] , true);
}
else{
return null;
}
}
function get_job_result($job_id=null){
if(!$job_id){return [];}
$cmd = <<<__CMD__
curl -s --location --request GET "https://{$this->domain}/v3/job/result/{$job_id}?format=json" \
--header "Authorization: TD1 {$this->api_key}"
__CMD__;
exec($cmd , $res);
return json_decode("[". implode(",", $res) ."]" , true);
}
function combine_result_data($job_id=null){
if(!$this->datas || !$job_id){return;}
$cmd = <<<__CMD__
curl -s --location --request GET "https://{$this->domain}/v3/job/show/{$job_id}" \
--header "Authorization: TD1 {$this->api_key}"
__CMD__;
exec($cmd, $res);
if(!$res){return;}
$res_data = json_decode($res[0],true);
$hive_result_schema = json_decode($res_data["hive_result_schema"] , true);
$schema = array_map(function($e=[]){
return $e[0];
}, $hive_result_schema);
if($schema){
for($i=0; $i<count($this->datas); $i++){
$this->datas[$i] = array_combine($schema, $this->datas[$i]);
}
}
}
}
Howto use
基本的に、コマンドラインで使う仕様にしています。
※理由としては、サーバーアクセスして、データ取得するまで、手続きが多く、タイムアウトしてしまうリスクが高いので、
コマンドツールとして、使ってください。
APIとして使ってもいいですが、戻り値を得るまでの時間を考えると、管理ツールで使用するぐらいの使い方に留めておいた方がいいでしょう。
1. コマンドラインを実行するPHPを用意
上記のソースコードをライブラリファイルとして設置して、使いたいphpでrequireします。
run.php
<?php
require_once(__DIR__."/treasure_data.php");
// クエリをセットする
$query = <<<SQL
SELECT *
FROM 対象テーブル
WHERE 条件
SQL;
$response = new Td([
"query" => $query,
"api_key" => "※Treasure dataのapi-keyを入力",
"domain" => "api.treasuredata.com",
"sleep_sec" => 5,
]);
print_r($response_datas);
2. API-keyをセット
上記コードのapi_keyの値に、Treasure dataのapi-keyの値(アカウント事に異なります)をセットします。
API-KEYの値は、管理画面の下記リンクから確認できます。
3. TreasureDataのURLをセット
こちらの環境では、「api.treasuredata.com」でアクセスできたんですが、
どうやら、それ以外のURLじゃないとデータが取得できない場合があるらしいので、うまく動作しない場合は、下記のURLでも試してみてください。(日本仕様のみ)
※domainの値を書き換えてください。
api.treasuredata.co.jp
api.ap02.treasuredata.com
api.eu01.treasuredata.com
4. クエリの登録
取得したいデータのクエリをSQLのヒアドキュメント箇所に記述(書き換え)してください。
クエリを動的に扱いたい場合などは、別途テキスト対応だったり、HTMLのtextareaなどを組み合わせて組み立ててください。
実行と解説
% php run.php
1. make_job
- job_id : 2541884841
2. get status
*************
3. get query result
設定が完了したら、上記コマンドを実行すると、コマンドラインに表示が出て結果が得られます。
解説
Treasure dataは、膨大データを扱い事を目的にしているため、複数のデータサーバーにデータが格納される仕組みです。
そのため、jobというque処理を受け付けサーバーで作ってから、バッチ処理のようにjobを実行していく流れになります。
処理の流れとして、
job作成 -> status確認
├ (runningの場合) -> 処理中のため、success確認を再実行
└ (successの場合) -> データ取得が完了 -> jobの結果を取得
簡単にフローを書くと上記のような工程で、中に分岐処理が入る仕様になります。
それぞれを、phpでは、curlコマンドで実施していて、直接コマンドで実行しても値は得られますが、この流れを一連のメソッド(エンティティ)にしておくことで、時間がかかりますが、ワンコマンドで結果が得られるようになります。
もちろん、失敗することもありますが、こちらの環境では、ほぼ問題なくデータ取得できるようになりました。
AIもいいけどバッチもね!
こうした手順をバッチ化させてプログラミングしておくことは、仕事の効率において非常に有効であることは、誰が考えても明確です。
こうしたプログラムをいくつ作ったかでエンジニアのスキルレベルが測れると言っても過言ではないぐらい、
プログラミングの基本中の基本です。
でも、ネットで検索してもTreasureDataに関するこうした記事を書いている人がいなかったので、今回自分が掲載しておきました。
誰か一人でもこの記事を参考にしてくれるといいなあ〜と思いながら、備忘録を書いておいて、今後の記憶の片隅に残せた事に安心できました。
ふ〜お疲れ様でした。
0 件のコメント:
コメントを投稿