【一般】東京都オープンデータソースAPIを活用してみる（データ取得編）

基礎準備編では、[Sharperlight](https://sharperlight.jp/)ファウンドリを用いてデータベースとデータモデルの設計を行うところまでを記事にしました。
今回は、Sharperlightスケジューラを使用して、APIエンドポイントからデータを取得する処理を作り込んでいきます。

その前に、前回作成したデータベースとデータモデルに少し修正をかけます。今回の記事を書く準備中に`ちょっとこうした方がいいかなっ`てところを見つけたので。
Sharperlightファウンドリ使用して変更を行いたいと思います。まだデータベースは空っぽだし、データモデルを使用したSharperlightオブジェクトも作っていないので再作成ということでいきます。

前回作成したSharperlightファウンドリの定義ファイルを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/6725000b-a45f-512c-4b13-1a0f8f500cbd.png)
ファウンドリが開いたら`フィールド`タブへ移動します。そしてテーブルドロップダウンリストから対象テーブル（一つしかないね:sweat_smile:）を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/b43e2168-1dec-05c1-5774-6598f2493ba8.png)
各フィールドのSQL列名を変更していきます。返されるJSONデータのフィールド名を使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/5ca5cc5c-2ac8-b3d3-eb77-6b1002cfe05e.png)
また、あるレコードには**患者_接触歴の有無フラグ**の代わりに、**退院済フラグ**というフィールドがあったり、その逆で**退院済フラグ**の代わりに**患者_接触歴の有無フラグ**フィールドがあったりすることも発見。その両方が存在するケースも。更には"患者_居住地"というフィールドの存在も確認。とほほ:joy:、一定ではないんですね。とりあえず全て追加しておきましょう。
フラグフィールドはYes/NoのBooleanフィールドにしようと思ったけど、存在しない場合のことを考えて文字列フィールドにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/4ec40956-68b1-0db4-dab2-52841ac32e28.png)
変更が済んだら、`保存`、`検証`そして`実行`を行います。
`実行`ボタンを押すと、このようなメッセージが表示されるので、`Yes`で続行。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/75021f9c-b603-5132-fe22-e5155985d0a5.png)
データモデルも上書きします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/329bbe6f-0fbc-7d91-9981-5c3bcc9399d4.png)
正常に終了したら、データベースとデータモデルを確認してみましょう。
データベースも作り直されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/1c114334-e863-9514-4cf3-652393f82f08.png)
データモデルもいい感じですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/51f33410-02bb-5cfd-9365-6730d8a5cb77.png)

ではSharperlightスケジューラを使用して、APIエンドポイントからデータを取得してみましょう。
JavaScriptでタスクを作っていこうと思います。
`データの取得`タスクでは、APIエンドポイントからのデータを受け取り、JSONファイルとしてファイルシステムに保存します。

では、Sharperlightスケジューラを起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/03488c1b-cc27-05b8-6e5e-f2ee643129af.png)
### データの取得 ###
**コード**、**グループ**、**説明**等を記入します。作業用フォルダをパラメータとして設定。一度保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/9961a7b8-e9df-b507-86b3-f2ac0426b8f6.png)
再度タスクを開き`アクション`タブに移動します。`新規`アイコンを利用してJavaScriptアクションを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/d5af77c4-fc40-e158-0a70-59652401c846.png)
JavaScriptアクションが追加されると下部に編集領域が現れるので、以下のコードを貼り付けます。
```
lib_task.LogMessage("START");

var baseURL = "https://api.data.metro.tokyo.lg.jp/v1/";
var endPoint = "Covid19Patient";
var queryOptions = ""; 
var limit = 1000;
var fromDateFilter = "2022-09-01";
var tillDateFilter = "2022-09-30";
var headers = {
    'accept': 'application/json'
};
var page = 1;
var workfolder = lib_task.ParamGet("WorkFolder");
var cursor = "";

//===============================================================================================================
// エンドポイントにリクエストを出して、データを取得する。
// 1000件のレコードを1 JSONファイルとして保存する 
//===============================================================================================================
while (page<1001){ 
    if (lib_task.state.abort ) { break; }
    
    
    // リクエストURLの作成
    if (page > 1){    
        queryOptions = "?cursor=" + lib_data.UrlEncode(cursor) + "&limit=" + limit.toString() + "&from=" + fromDateFilter + "&till=" + tillDateFilter;
	}else{
        queryOptions = "?limit=" + limit.toString() + "&from=" + fromDateFilter + "&till=" + tillDateFilter;
    }
    var connections_url = baseURL + endPoint + queryOptions;
    lib_task.LogMessage(connections_url);

    // リクエストを行う
    var response = lib_sys.urlContent.Get(connections_url, '', headers);
        
    // レスポンスをJSONファイルとして保存する
    var filePath = workfolder + "stagingResult_" + page.toString() + ".json";
    lib_sys.io.file.WriteAllText(filePath, response);                    
        
    try{
        // 次のデータページの存在をチェックする
        var rec = JSON.parse(response);
        lib_task.LogMessage("cursor=" + rec[1].moreResults);
        if (rec[1].moreResults != "NO_MORE_RESULTS"){
            cursor = rec[1].endCursor;
            page++;
            console.log(page);
        }else{
            lib_task.LogMessage("FINISH");
            break;
        }
    }catch (err){
        lib_task.LogMessage(err);
        break;
    }
}                 
```
コード内に現れるlib_sys.io.file.WriteAllText等は、Sharperlightエンジンが提供する関数です。
lib_task.ParamGet: タスクに渡されるパラメータの値を取得する。
lib_sys.urlContent.Get: Getリクエストを行う。
lib_sys.io.file.WriteAllText: データをファイルとして保存する。
lib_task.LogMessage: タスクの実行ログに記録する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/07b9fdb3-cd3b-1413-b250-f82433a34770.png)
`適用`ボタンで再度保存しましょう。いままでの作業が水の泡なんていやですからね。
以上でGetリクエストを発してデータを取得して、JSONファイルとして指定のフォルダに保存するという一連の処理は完成です。
`接続テスト`ボタンで実行試験を行うこともできます。また`OK`ボタンで保存したうえで、タスク一覧の右クリックメニューから実行を選択することもできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/4a8d77fb-119b-fb71-5765-aac41520ead9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/1828a6cd-cc80-16e3-d875-a017b392da9e.png)
タスクが正常に動作するとJSONファイルは、パラメータで渡された作業フォルダであるこのフォルダに保存されます。
```
C:\Users\{あなたのアカウント名}\AppData\Local\Temp\SL_Temp\SL_Inst_MAIN\SL_Scheduler\
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/8c0039b7-aff7-d5d1-afe6-806ef1fa4606.png)

先ずは動くタスクを作成ということで、データの取得範囲をJavaScript埋め込みで**2022-09-01**から**2022-09-30**としました。
```
var fromDateFilter = "2022-09-01";
var tillDateFilter = "2022-09-30";
```
このタスクを自動化するに辺り、この日付もパラメータにしたいです。
### タスクの自動化 ###
どの日付範囲のデータを取得するかを決めて、日付を先のJavaScriptアクションにパラメータとして渡します。
タスクは毎日実行させるつもりなので、データを書き込んでいるテーブルから最新の日付(MAX(J001.[公表_年月日]))を取得して、その日付をFrom値とします。To値はFrom値に1を足した日付としましょうか。
**From** `MAX(J001.[公表_年月日])` **To** `From値 + 1日`
これをSharperlightクエリで算出するようにします。なので先のタスクを開いて**クエリの組み合わせ**アクションを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/56f8c34e-8c2c-ae2f-ffe3-b569179931d5.png)
クエリはこんな感じですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/b8037e05-1b73-8f75-3209-7e7166739f89.png)
`日付範囲始め`、つまり`From値`は、テーブルの公表年月日をこのように形式設定して文字列として返します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/cee53ec3-61c2-d754-4b4d-9a5799995e6f.png)
`日付範囲終わり`、つまり`To値`は、テーブルの公表年月日に1日を足した日付をこのように形式設定して文字列として返します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/a0e52aa4-d0c0-57f4-792d-aa2ef4bb4630.png)
これらの値を先のJavaScriptに渡します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/a6b466e5-1a84-721f-efef-d71b22395b9f.png)
JavaScriptアクションの後に**クエリの組み合わせ終了**アクションを追加して完成。

これで毎回タスクが決まった時間に実行されるたびにクエリで算出された日付を利用して、APIエンドポイントからデータを取得しJSONファイルとして保存することができます。

そうそうタスクが実行開始されてすぐ、ワークフォルダのJSONファイルをクリアした方がいいですね。**ファイル削除**アクションも追加しましょうか。このような感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/3c8cc31d-f527-fd78-e57b-ed8006009273.png)

以上でデータ取得の自動化の作成が終了です。後はこのタスクが実行された直後に、今度は保存されているJSONファイルの内容、つまりデータをデータベースに書き込むタスクが必要ですね。
それについては次回の記事で。

では、失礼します。