Technical Articles
SAP CP上でのバックエンド開発(Node.jsとSAP HANA)
第2回 東京公共交通オープンデータチャレンジに応募した「まよワン!じっこくん」の連載記事の第5回です。
- 東京公共交通オープンデータチャレンジに応募してみた
- 「まよワン!じっこくん」とは?(アプリケーション説明とアーキテクチャ概要)
- デザインシンキングでアプリ要件を考えてみる(デザインシンキング)
- チャットボットの開発(SAP Conversational AI)
- SAP CP上でのバックエンド開発(Node.jsとSAP HANA) ←今回はコチラ
- SAP CPで開発したアプリをJenkinsでDevOps
こんにちは! DBS Japan 小林です。
オープンデータチャレンジでは、バックエンド(Node.js/SAP HANA)の開発を担当しました。
こちらのブログでは、どのような仕組みでじっこくんが動いているかについて、Node.js/SAP HANAの観点から紹介させて頂きたいと思います。
全体のアーキテクチャの中で言うと、赤枠部分になります。
バックエンドの役割
じっこくんでは、SAP Conversational AI (=Recast.AI) が、LINEでの会話を通して検索に必要な情報を集めます。そのままConversational AIが、時刻表検索をするAPIを直接呼び出せれば良いのですが、集めた情報そのままのフォーマットでは、時刻表検索のAPIを呼び出すことができません。
そこで、バックエンドではConversational AIからデータを受け取り、時刻表検索ができるような形に変換、受け取ったデータをConversational AIが理解できる形で返す。といったような、データの橋渡しをしています。
バックエンドの処理の流れ
バックエンド側で時刻の検索を行うNode.jsアプリケーションでは、以下のような流れで時刻表情報を取得しています。
- Conversational AIから乗り換え情報の検索に必要な情報を受け取る。
- 受け取った情報をキーにして、SAP Cloud Platform(以下SCP)上のSAP HANA(以下 HANA)から、時刻表を検索できる形のデータを取得。同時に検索履歴を書き込む。(いつも乗る路線を検索する”いつもの”機能で使用)
- 時刻表検索をするオープンデータチャレンジのAPIを呼び出し、指定された条件の時刻表情報を取得。
- Conversational AIへ時刻表情報を返す。
Conversational AIとのデータのやりとり
Conversational AIからは、JSON※というデータの形でやりとりをします。
※JavaScript Object Notation というデータフォーマット
↓のような形式です。”memory”:{~}の中に、LINEの会話で取得される情報、”participant_data”:{~}には、LINEのユーザIDが格納されています。
{
“conversation”: {
“memory”: {
“line”: {“value”: “有楽町線”},
“stationOn”: {“value”: “池袋”},
“stationOff”: {“value”: “飯田橋”},
“time”: {“value”: “19:30”},
“isHoliday”: {“value”: “平日”}
},
“participant_data”: {“userName”:”Haruyuki Kobayashi”}
}
}
例えば、Node.jsで”有楽町線”という値を取り出したい場合↓のように変数を定義します。
var InSearchTerm = {InRailway : req.body.conversation.memory.line.value};
データを返す時には、シンプルにテキストをまるっと返しています。
{
“replies”: [
{
“type”: “text”,
“content”: “有楽町線の池袋から飯田橋行きの平日ダイヤで19時30分から10本の電車は、\n19:33 普通 新木場行\n19:38 普通 新木場行\n19:43 普通 新木場行\n19:48 普通 新木場行\n19:53 普通 新木場行\n19:59 普通 新木場行\n20:04 普通 新木場行\n20:09 普通 新木場行\n20:14 普通 新木場行\n20:19 普通 新木場行\nがあるよん。 \nデータ取得日時(2019年02月14日(木) 午後 02:54:14 (JST))”
}
]
}
SCP 上のNode.jsアプリケーションとHANAの接続
今回SCP上で作成したNode.jsアプリケーションは、HANAからインポートした駅や路線名のデータを読み込んだり、検索履歴を書き込む処理を行うため、アプリケーションがSCP上のHANAにアクセスできる必要があります。
Node.jsアプリケーションからHANAへの接続を設定するのはとても簡単で、下記ようにライブラリを読み込むだけで、HANAへの接続が可能です。
var xsenv = require(“@sap/xsenv”);
var hdbext = require(“@sap/hdbext”);
SQLの発行は、以下のコマンドで可能です。下のようなコマンドだと、resultsに結果が配列として格納されます。
1.実行するSQL文を変数として格納
var sql = ‘実行するSQL文’
2.SQL文の実行
req.db.prepare(sql, function (err, statement){
//エラー処理等省略
statement.exec(sql, function (err, results) {}
}
実際のコードでは、HANAによる、高速なレスポンスを期待し、ロジックをHANA側に寄せる方向で設計をしました。
そこで今回は、複雑なSQLを書くとコードが読みづらくなる&処理をシンプルするため、HANA側でテーブルファンクション※を定義し、使用ました。
※SQLスクリプトで実装する、ユーザ定義関数
開発環境
SCP上でアプリケーションを開発する為。開発ではSCP上のWebIDEを使用しました。開発の画面イメージはこんな感じ。
コンパイラのアップデートなどが頻繁にあり、とてもCloudを感じました。。
バージョン・タスク管理
今回は、複数人でアプリの開発をしました。その為、ソースコードのバージョンと、メンバーのタスクの管理をする必要がありました。
SCPではGitHubを用いたバージョン管理が可能なので、バージョンとタスクの管理にはGitHubを利用しました。開発/タスク(Issue)のルールは、下記のような感じです。
開発期間を2つに分けて開発を行い、私は後半の開発期間のリーダーを務めたのですが、途中でメンバーが忙しくなってしまったので、Issueに対して優先度をつけて担当者の再分配を行うなどの調整が大変でした。。。
開発ルール
- GitHubのBranchはmasterを使用する。Assignされた担当者が直接git pushでmasterを更新する。
- Commitは必ずこまめに行い、基本的にはAssignされた1Issue単位で行う。1日1度を目安に、Repositoryが動く範囲でCommitする。
- Commitコメントは必ずつける。ルールは” #<Issue number> 作業内容“とする。最初に半角スペースをつけて、GitHubのIssue numberを#込みで記入する(そのCommitがどのIssueに紐づくのかGithub側で追跡する為)。
Issue作成ルール
- 必ずProjectを割り当てる(Project側で全体感を把握することができる為)。
- 必ず人をAssignする(作業する人を明確にして作業漏れを無くす為。AssignはLeadが、もしくは当事者同士の話し合いで変更可能)。
- labelはenhancementとbugのみを必ず使用する。
振り返り、感想など
アプリ的なところですと、プログラム内の機能をもっと細分化して関数化できれば、今後の拡張やメンテナンス性が向上するかなと感じています。
また、今回は複数人で開発を行ったので、Issueの割り振り調整が必要な場面が多々あり、その点は苦労したポイントです。しかし、クラウドの開発環境を使用したので、メンバーが増えるたびにローカルの開発環境を設定して。。という作業はなかったので、その点はとても楽だったなと感じています。
個人的には、今回のオープンデータチャレンジで、初めてプログラムを書いてアプリを作成するという経験をしました。(担当したのはごくごく一部ですが。。。)
当初はソースコードに何が書いてあったのかもわからなかったのですが、オンラインのチュートリアルなどを見て、どうにか自分が書いたコードが動いたときはとても嬉しかったです!!
最後まで読んでいただき、ありがとうございました。
是非、他のトピックのブログもご覧になってみてください。