IICSのAPI(CAI)を作ってGoogle Apps Scriptからデータを送る

Informatica Intelligent Cloud Services(IICS)の Cloud Application Integration(CAI)機能でAPIを構築する。 Google Apps Script(GAS)でスプレッドシート(Google Sheets)のデータをAPIに送信する。
2020.12.14

本エントリはクラスメソッド インフォマティカ Advent Calendar 2020のエントリです。

データアナリティクス事業本部、池田です。 アドベントカレンダー14日目です!もう半分以上終わりましたねー。
以前のブログ で、Informatica Intelligent Cloud Services(以下IICS)の コネクタ を使ってGoogle スプレッドシート(Google Sheets、以下スプレッドシート)からデータを取得してみました。 IICSには、 Cloud Application Integration (アプリケーション統合、以下CAI)というAPIを構築できる機能があります。 これを使ってみたかったので、スプレッドシートのデータをIICSへ持ってくる流れを、 コネクタを使わずにCAIと Google Apps Script (以下GAS)を使って構築してみます。

CAIの基本的な部分については、以下のブログなどが良いと思います。

IICS(CAI)のチュートリアルを試してみる(Hello World編)

APIの構築

データを格納する「プロセスオブジェクト」、 結果を Amazon S3 に吐き出すのでS3の「アプリケーション接続」、 CAIの「プロセス」を作成します。

プロセスオブジェクト

プロセスオブジェクト を作成します。
(個人的にはJavaのBeanみたいなもんだと雑にイメージしています。)

「アプリケーション統合」の画面から、新規作成を始めます。

名前をつけ、格納したいスプレッドシートの列に合わせてフィールドを定義し、 保存します。

↑簡略化のため、今回は全てテキストで指定しました。 もちろん型は他にもいろいろとありますし、 プロセスオブジェクトを指定して入れ子を作ることもできそうです。

アプリケーション接続

今回も受け取ったデータをS3に吐き出すだけにするので、 S3のコネクタアプリケーション接続を作成します。
CAIのコネクタは、Cloud Data Integration(CDI)機能(「データ統合」画面)のコネクタとはまた別物のようです。

新規で作り始めます。

詳細欄では、名前をつけ、タイプにS3を指定します。 実行には使用するランタイム環境を指定しますが、準備しておいたSecure Agentを設定しました。 プロパティの欄では、S3にアクセスできるキーを設定します。

今回は出力に使うので、「イベントターゲット」のタブに移動して、 ターゲットを追加します。 必須なのは出力に必要なS3バケット名です。(作成済み。) 出力ファイル形式などもこのタブで設定できます。

保存&テストを実行し、問題が無ければ、 パブリッシュを行い、接続を使えるようにします。

(これを忘れると、次節のプロセスの作成中にこの接続が使用できません。)

プロセス

API構築のメインの部分、プロセスです。
この辺 やら この辺 を参考にしました。

新規で作っていきます。

(「開始」ステップが選択された状態で、)プロセスに名前をつけます。 APIのURLにもこれが含まれます。

「開始」フォームで、匿名アクセスを許可 を有効にします。  ※今回は簡略化のため。

「入力フィールド」フォームで受け付けるデータの形を定義します。
今回は data という名前で、 「タイプ」はカスタムタイプから、作成しておいたプロセスオブジェクトを リストを許可して指定します。

「出力フィールド」フォームでは、APIが返す値を設定します。

今回は、送付されたレコードの件数を cnt という名前で返してみます。


「割り当て」をステップとして追加して、 直前で作成した cntdata の件数を割り当てます。

計算式: list:count($input.data)


S3に吐き出す処理として、「サービス」を次のステップとして追加します。
「サービス」フォームで、前節でパブリッシュしておいたアプリケーション接続を選択し、 「アクション」にはイベントターゲット名( AwsS3DelimitedContentWriter )を設定します。

「入力フィールド」で、書き出すファイルの設定をします。

「計算式」を選択し、 XQuery というもので記述するようです…

この辺のガイド を参考に、↓作成してみました。

<StoreS3DelimitedContentRequest>
    <!-- create S3 object metadata -->
    <s3ObjectParameters>
        <!-- object key, is required -->
        <awsS3Key>output.csv</awsS3Key>
    </s3ObjectParameters>

    <header>
        <name>post-title</name>
        <fieldIndex>1</fieldIndex>
    </header>
    <header>
        <name>date</name>
        <fieldIndex>2</fieldIndex>
    </header>
    <header>
        <name>author-name</name>
        <fieldIndex>3</fieldIndex>
    </header>
    <header>
        <name>href</name>
        <fieldIndex>4</fieldIndex>
    </header>

    {for $x in $input.data
    return
    <customObjects>
        <post-title>{$x/post-title/text()}</post-title>
        <date>{$x/date/text()}</date>
        <author-name>{$x/author-name/text()}</author-name>
        <href>{$x/href/text()}</href>
    </customObjects>
    }

</StoreS3DelimitedContentRequest>

(もっと効率良い書き方がありそう…)

保存し、パブリッシュしてAPIを公開します。

「プロパティの詳細」から、接続するための「サービスURL」を控えます。

APIの構築はこれで終わりです。 値を返すだけのAPIの構築なら簡単にできて、私はS3に書き出す部分で苦労しました。

APIのテスト

APIができたので、簡単につないでみます。

前節でパブリッシュした「サービスURL」にJavaScriptのfetch()で2レコードPOSTしてみます。

数秒で無事、件数が返ってきました。

S3バケットにも無事ファイルが作成されていました。

GAS

前章でAPIはできて、接続もできているので、この章はもはやおまけです。 正直ただGASを使いたいだけです。

スプレッドシートは前回のブログと同じで、、、
IMPORTXML 関数を使って、 弊社ブログのページ をスクレイピングしたものです。
(↑ややこしいので画像の img 列(D列)は使いません。)

今回はスプレッドシートにバンドルしてGASを作成します。


↓コードはこんな感じです。

クリックでコードを表示する/折りたたむ

main.gs

// メニュー追加
function onOpen() {
    var ui = SpreadsheetApp.getUi();
    var menu = ui.createMenu("IICS連携");
    menu.addItem("実行", "sendIics");
    menu.addToUi();
}

// データの取得
function getJsonData() {
    var activeSheet = SpreadsheetApp.getActiveSheet(),
        sheetData = activeSheet.getDataRange().getValues(),
        data;

    // ヘッダー分を削除
    sheetData.shift();
    // 形式の変更(二次元配列→オブジェクトの配列)
    data = sheetData.map(r => {
        return {
            "post-title": r[0],
            "date": r[1],
            "author-name": r[2],
            "href": r[4]
        }
    });

    return data;
}

// IICSのAPIへ送信
function sendIics() {
    var props = PropertiesService.getScriptProperties(),
        url = props.getProperty("IICS_API"),
        data, response;

    data = getJsonData();

    response = UrlFetchApp.fetch(url, {
            method: "post",
            contentType: "application/json; charset=utf-8",
            payload: JSON.stringify({
                data: data
            })
        });
    console.log(response.getContentText());
}

onOpen() 関数では、スプレッドシートのメニューに連携実行ボタンを追加しています。 ボタンを押すと後述の sendIics() 関数を実行します。

getJsonData() 関数では、スプレッドシートからデータを取得しています。
.getValues() してセル群の値を取得すると、 そのままだと二次元配列( [[値a1,値b1,…],[値a2,…],…] )の形なのですが、 この形のままCAI側で上手くさばく方法が私では分かりませんでした… なので、オブジェクトの配列( [{post-title:値a1,date:値b1,…},{post-title:値a2,…},…] )の形に変換しています。

sendIics() 関数では、データの取得関数を呼び出しデータを取得したのち、 UrlFetchApp.fetch() でAPIにリクエストを投げています。
コンテントタイプに charset=utf-8 を指定しないと、日本語が文字化けしてしまいました。

使用するAPIのURLは「スクリプトのプロパティ」として登録しています。


前述の連携実行ボタンから実行してみると、 無事スプレッドシートの内容がS3へ連携されました!!!

おわりに

APIを作って無事連携することができました。
APIを使うことで、IICSの活用の幅がいろいろと広がるのではないかと思います。たぶん。

今回はアドベントカレンダーということで作業できる時間に限りがあったので、 正直いろいろ心残りがあります…

  • プロセスの作成で 匿名アクセスを許可 しないで、認証?をつけたかった
  • S3に書き出すXMLの計算式はもっと効率的なのが書けそう
  • GAS側で形式を改変せず、二次元配列のままCAIでさばきたかった

この辺は気が向いたら追記するか、別途ブログにします…たぶん。

参考文献