製品をチェック

製品の情報と30日間無償トライアル

Azure Data Lake Storage 連携ソリューション 相談したい

AngularJS を使用し、Azure Data Lake Storage データで動的なWeb ページを構築

Azure Data Lake Storage に接続できるシングルページアプリケーションを作成します。

古川えりか
コンテンツスペシャリスト

最終更新日:2022-10-13
azuredatalake ロゴ

CData

apiserver ロゴ画像
AngularJS ロゴ

こんにちは!ドライバー周りのヘルプドキュメントを担当している古川です。

AngularJS (Angular) は、動的なWeb アプリの構造フレームワークです。CData API サーバーであるAngular およびADO.NET Provider for ADLS (または240+ その他のADO.NET Providers) のCData API サーバーを使用して、Azure Data Lake Storage からリアルタイムデータにアクセスできるシングルページアプリケーション(SPAs) を構築できます。 この記事では、CData API サーバーの設定と、Azure Data Lake Storage へのライブアクセスを持つ単純なSPA の作成について説明します。 SPA はHTML テーブルを動的に作成して入力します。

API サーバーをセットアップ

ダウンロードしていない場合、CData API サーバーをダウンロードする必要があります。API サーバーとADO.NET プロバイダfor ADLS をインストールしてアプリケーションを実行し、Azure Data Lake Storage に接続するようにドライバーを構成してから、SPA にアクセスしたい任意のテーブルのOData フィードを作成するようにドライバーを構成する必要があります。

CORS を有効にする

AngularJS では、サーバーでCORS (Cross-origin resource sharing) を有効にする必要があります。API サーバーの[SETTINGS Server]タブに移動すると、CORS を有効にできます。 以下の設定を調整する必要があります。

  • チェックボックスをクリックして「Enable cross-origin resource sharing (CORS)]をクリックします。
  • チェックボックスをクリックして[Allow all domains without '*']を選択するか、Access-Control-Allow-Origin で接続を許可するドメインを指定します。
  • Access-Control-Allow-Methods を[GET,PUT,POST,OPTIONS]に設定します。
  • Access-Control-Allow-Headers を[authorization]に設定します。
  • [Save Changes]をクリックします。

Azure Data Lake Storage への接続を構成

Azure Data Lake Storage データに接続するようにAPI サーバーを構成するには、[Settings]ページの[Connections]タブに移動する必要があります。

接続に名前を付け、データベースとして[Other]を選択してADO.NET プロバイダ(System.Data.CData.ADLS) を設定します。そして、接続文字列を作成するか、接続プロパティを設定します。

Azure Data Lake Storage 接続プロパティの取得・設定方法

Azure Data Lake Storage Gen 2 への接続

Gen 2 Data Lake Storage アカウントに接続するには、以下のプロパティを設定します。

  • Account:ストレージアカウントの名前。
  • FileSystem:このアカウントに使用されるファイルシステム名。例えば、Azure Blob コンテナの名前。
  • Directory(オプション):レプリケートされたファイルが保存される場所へのパス。パスが指定されない場合、ファイルはルートディレクトリに保存されます。

Azure Data Lake Storage Gen 2 への認証

本製品は、次の4つの認証方法をサポートします:アクセスキーの使用、共有アクセス署名の使用、Azure Active Directory OAuth(AzureAD)、Managed Service Identity(AzureMSI)。

アクセスキー

アクセスキーを使用して接続するには、はじめにADLS Gen2 ストレージアカウントで利用可能なアクセスキーを取得する必要があります。

Azure ポータルで:

  1. ADLS Gen2 ストレージアカウントにアクセスします。
  2. 設定でアクセスキーを選択します。
  3. 利用可能なアクセスキーの1つの値をAccessKey 接続プロパティにコピーします。
  4. 接続の準備ができたら、次のプロパティを設定します。

    • AuthSchemeAccessKey
    • AccessKey:先にAzure ポータルで取得したアクセスキーの値。

共有アクセス署名(SAS)

共有アクセス署名を使用して接続するには、はじめにAzure Storage Explorer ツールを使用して署名を生成する必要があります。

接続の準備ができたら、次のプロパティを設定します。

  • AuthSchemeSAS
  • SharedAccessSignature:先に生成した共有アクセス署名の値。

AzureAD、AzureMSI での認証方法については、ヘルプドキュメントの「Azure Data Lake Storage Gen 2 への認証」セクションを参照してください。

Connecting to Azure Data Lake Storage.(Salesforce is shown.)

ユーザーの構成

次に、API サーバーを介してAzure Data Lake Storage データにアクセスするユーザーを作成します。[Settings]ページの[Users]タブでユーザーを追加及び構成できます。 データを表示するための単純なSPA のみを作成しているため、読み取り専用アクセス権を持つユーザーを作成します。 [ Add]をクリックし、ユーザに名前を付けて[Privileges]で[GET]を選択します。また、すべてのIP アドレスからの接続を許可します。

Creating a new user.(Salesforce is shown.)

スクリーンショットにあるように、読み取り及び書き込みのアクセス権が設定されたユーザーがすでにあります。この記事では、関連付けられた認証トークンを使用し、読み取り専用ユーザーでAPI サーバーにアクセスします。

API Server users.(Salesforce is shown.)

テーブルにアクセス

ユーザーを作成したらAzure Data Lake Storage エンティティにテーブルとしてアクセスできるようになります。テーブルを有効にするためには、[Settings]ページの[Resources]タブにある[Add Resources]ボタンをクリックします。 アクセスするテーブルを選択し、[Save Changes]をクリックします。リソースを追加するとAzure Data Lake Storage データのOData フィードが作成されます。

Adding tables from Azure Data Lake Storage.(Salesforce is shown.)

OData フィードのサンプルURL

Azure Data Lake Storage への接続を構成し、ユーザーを作成してAPI サーバーにテーブルを追加すれば、それらのテーブルのOData フィードにアクセスできます。 以下は、テーブルにアクセスするためのURL とテーブルのリストです。テーブルへのアクセスについては、([API Server Web]ページの右上にあるAPI リンクをクリックして)API サーバーのAPI ページに移動できます。 URL には、API サーバーのアドレスポートが必要です。 Angular を使用しているため、デフォルトではJSON データを返さないURL の末尾に@json パラメータを追加します。

Table         URL
Entity (table) List http://address:port/api.rsc/
Metadata for table Resources http://address:port/api.rsc/Resources/$metadata?@json
Account http://address:port/api.rsc/Resources

返されるフィールドを制限する場合には、標準のOData フィードと同様に、$select パラメータを$filter、$orderby、$skip、$top などの他の標準のOData URL パラメータとともにクエリに追加できます。 サポートされているOData クエリの詳細については、ヘルプドキュメントを参照してください。

シングルページアプリケーションの構築

API サーバーのセットアップが完了したら、SPA を構築する準備が整います。これは単純なデモンストレーションなので、すべてのCSS、スクリプト、およびAngular コントローラーを1 つのファイルに含め、AngularJS サービス、ファクトリ、およびカスタムディレクティブによって提供される機能を意図的に使用しないようにします。

CSS 定義とAngularJS ライブラリのインポート

まずCSS ルールセットをいくつか作成し、table、th、td、tr 要素を変更してデータのテーブルをフォーマットします。また、SPA で使用するためにAngularJS ライブラリをインポートする必要があります。


  <style>
  table, th, td {
    border:1px solid grey;
    border-collapse: collapse;
    padding:5px;
  }
  table tr:nth-child(odd) {
    background-color: #f1f1f1;
  }
  table tr:nth-child(even) {
    background-color: #ffffff;
  }
  </style>
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>

Angular アプリとコントローラーオブジェクトの作成と参照

次に、HTML の[body]タグにng-app ディレクティブとng-controller ディレクティブを追加します。これは、本体がAngular を使用す唯一の場所であるために必要な操作です。 そして、HTML 本文の最後にAngular アプリとコントローラーを作成及び定義するスクリプトタグを作成します。


<body ng-app="DataApp" ng-controller="SimpleController">
...
<script>
var app = angular.module('DataApp', []);
app.controller('SimpleController', function($scope, $http) {
    //we will add code here
    });
</script>
</body>

コントローラーの定義

ここでのコントローラーはAngular オブジェクトを初期化してSPA を設定するinit、選択したテーブルのカラムを取得するgetTableColumns、選択したカラムから選択したフィールドのデータを取得するgetTableData の3つの関数で構成されます。 コントローラを作成するときの最初のアクションとして、init 関数を呼び出します。 他のすべての関数は必要に応じて呼び出され、これらの関数呼び出しでAzure Data Lake Storage データを取得するために、API サーバーに対して必要なHTTP GET 呼び出しを行います。


init();

/*
 * Initialize the data object, which will be used with Angular to
 * build the different parts of our SPA and to retrieve data from
 * the API Server.
 */
function init() {
  $scope.data = {
  availableTables: [],
                 availableColumns: [],
                 selectedTable: {},
                 tableData: []
  };

  /*
   * Call to the API Server to get the list of Tables, select the
   * first table by default, and retrieve the available columns.
   * 
   * The call to the API Server returns standard OData, so the 
   * data we need is in the value object in the JSON returned.
   */
  $http.get("http://server:port/api.rsc",{headers: {"Authorization":"Basic "  + btoa("MyUser:MyAuthtoken")}})
    .then(function (response) {
        $scope.data.availableTables = response.data.value;
        $scope.data.selectedTable = $scope.data.availableTables[0];
        $scope.getTableColumns();
        });
}

/*
 * Call to the API Server to get the list of columns for the 
 * selected table.
 *
 * The data returned here is not standard OData, so we drill 
 * down into the response to extract exactly the data we need
 * (an array of column names).
 *
 * With the column names retrieved, we will transform the array
 * of column names into an array of objects with a name and Id 
 * field, to be used when we build an HTML select.
 */
$scope.getTableColumns = function () {
  $scope.data.tableData = [];
  $scope.data.selectedColumns = [];
  table = $scope.data.selectedTable.url;
  if (table != "") {
    $http.get("http://server:port/api.rsc/" + table + "/$metadata?@json", {headers: {"Authorization":"Basic "  + btoa("MyUser:MyAuthtoken")}})
      .then(function (response) {
          $scope.data.availableColumns = response.data.items[0]["odata:cname"];
          for (i = 0; i < $scope.data.availableColumns.length; i++) {
            $scope.data.availableColumns[i] = { id: i, name: $scope.data.availableColumns[i] };
          }
          });
  }
} 

/*
 * Call to the API Server to get the requested data.We get the data 
 * based on the table selected in the associated HTML select. 
 * Then we create a comma-separated string of the selected columns.
 * 
 * With the table and columns known, we can make the appropriate call
 * to the API Server.Because the driver returns standard OData, the 
 * table data is found in the value field of the response.
 */ 
$scope.getTableData = function () {
  table = $scope.data.selectedTable.url;
  columnsArray = $scope.data.selectedColumns;
  columnString = "";
  for (i = 0; i < columnsArray.length; i++) {
    if (columnString != "") {
      columnString += ",";
    }
    columnString += columnsArray[i].name;
  }

  if (table != "") {
    $http.get("http://server:port/api.rsc/" + table + "?$select=" + columnString, {headers: {"Authorization":"Basic "  + btoa("MyUser:MyAuthtoken")}})
      .then(function (response) { $scope.data.tableData = response.data.value; });
  } else {
    $scope.data.tableData = [];
  }
}     

Web ページの構成

コントローラを定義したら、Angular を使用してWeb ページを構築する準備が整います。単純なページには、テーブルを選択するための選択ボックス、カラムを選択するための選択(複数)ボックス、データを取得するためのボタン、およびデータを表示するためのテーブルの4つの主要部分があります。 これら4つの部分の1つずつを通して、Angular の使用方法について説明します。

テーブルを選択

最初のselect 要素では、ng-options ディレクティブを使用し、使用可能なテーブル(前述のinit 関数から取得) を反復処理し、select 要素にデータを入力します。 ng-model ディレクティブを使用して、選択したオプションの値をdata.selectedTable フィールドに割り当てます。 選択したテーブルが変更された場合は、getTableColumns 関数を呼び出して使用可能なカラムを再設定します。


  <label>Select a Table</label>
  <br />
  <select name="tableDropDown" id="tableDropDown" 
          ng-options="table.name for table in data.availableTables track by table.url"
          ng-model="data.selectedTable"
          ng-change="getTableColumns()">
  </select>

カラムを選択

2番目のselect 要素では、再びng-options ディレクティブを使用しますが、今回は、(getTableColumns 関数によって取得された)使用可能なカラムを反復処理します。 使いやすさのために、select 要素に入力する前にカラムを名前でソートします。 この選択には複数 の属性が含まれているため、複数のカラムを選択できます。 選択した各列がdata.selectedColumns 配列に追加されます。カラムを選択すると、各列のテーブルヘッダーが作成されます(以下のデータテーブルのセクションを参照)。


  <label>Select Columns</label>
  <br />
  <select name="columnMultiple" id="columnMultiple"
          ng-options="column.name for column in data.availableColumns | orderBy:'name' track by column.id"
          ng-model="data.selectedColumns"
          multiple>
  </select>

テーブルデータを取得

このボタンでは、ボタンがクリックされるたびにgetTableData 関数を呼び出します。ユーザーがカラムを選択していない場合に、ng-disabled ディレクティブを使用してボタンを無効にしていることに注意してください。 また、選択したテーブルの名前でボタンのテキストを動的に更新します。


  <button name="getTableData" id="btnGetTableData" 
          ng-click="getTableData()" 
          ng-disabled="data.selectedColumns.length == 0">
  Get {{data.selectedTable.name}} Data
  </button>

テーブルデータを表示

このセクションは、選択したテーブルのデータを表示するというSPA の最終目標を満たしています。そのために、いくつかのng-repeat ディレクティブを使用します。1つは選択したカラムを反復処理してテーブルヘッダーを作成し、もう一つは返されたデータの行を反復処理して対応するデータを特定の行に表示します。

Angular を使用することで、表示するカラムを動的に決定できます。データがクリックされる「前」に選択されたカラムのみにデータが含まれることに注意してください。 使用可能なすべてのカラムを選択し、ボタンをクリックしてテーブルデータを取得してから、戻って別のカラムを選択または選択解除し、表示されるデータを変更することは簡単にできます。 選択したテーブルを変更すると、すべてのデータがクリアされます。


  <table>
    <tr>
      <th ng-repeat="column in data.selectedColumns | orderBy:'name'">{{column.name}}</th>
    </tr>
    <tr ng-repeat="row in data.tableData">
      <td ng-repeat="column in data.selectedColumns">{{ row[column.name] }}</td>
    </tr>
  </table>

アプリの完成

<!DOCTYPE html>

<html>
<style>
table, th, td {
border:1px solid grey;
        border-collapse: collapse;
padding:5px;
}
table tr:nth-child(odd) {
  background-color: #f1f1f1;
}
table tr:nth-child(even) {
  background-color: #ffffff;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body ng-app="DataApp" ng-controller="SimpleController"> 
<label>Select a Table</label>
<br>
<select name="tableDropDown" id="tableDropDown" 
ng-options="table.name for table in data.availableTables track by table.url" 
ng-model="data.selectedTable" 
ng-change="getTableColumns()">
</select>
<label>Select Columns</label>
<br />
<select name="columnMultiple" id="columnMultiple"
ng-options="column.name for column in data.availableColumns | orderBy:'name' track by column.id"
ng-model="data.selectedColumns"
multiple>
</select>
<button name="getTableData" id="btnGetTableData" 
ng-click="getTableData()" 
ng-disabled="data.selectedColumns.length == 0">
Get {{data.selectedTable.name}} Data
</button>
<br />
<br />

<table>
<tr>
<th ng-repeat="column in data.selectedColumns | orderBy:'name'">{{column.name}}</th>
</tr>
<tr ng-repeat="row in data.tableData">
<td ng-repeat="column in data.selectedColumns">{{ row[column.name] }}</td>
</tr>
</table>
<script>
var app = angular.module('DataApp', []);
app.controller('SimpleController', function($scope, $http) {
    init();

    /*
     * Initialize the data object, which will be used with Angular to
     * build the different parts of our SPA and to retrieve data from
     * the API Server.
     */
    function init() {
    $scope.data = {
    availableTables: [],
    availableColumns: [],
    selectedTable: {},
    tableData: []
};

/*
 * Call to the API Server to get the list of tables, select the
 * first table by default, and retrieve the available columns.
 * 
 * The call to the API Server returns standard OData, so the 
 * data we need is in the value object in the JSON returned.
 */
$http.get("http://server:port/api.rsc",{headers: {"Authorization":"Basic "  + btoa("MyUser:MyAuthtoken")}})
.then(function (response) {
    $scope.data.availableTables = response.data.value;
    $scope.data.selectedTable = $scope.data.availableTables[0];
    $scope.getTableColumns();
    });
}

/*
 * Call to the API Server to get the list of columns for the 
 * selected table.
 *
 * The data returned here is not standard OData, so we drill 
 * down into the response to extract exactly the data we need
 * (an array of column names).
 *
 * With the column names retrieved, we will transform the array
 * of column names into an array of objects with a name and Id 
 * field, to be used when we build an HTML select.
 */
$scope.getTableColumns = function () {
  $scope.data.tableData = [];
  $scope.data.selectedColumns = [];
  table = $scope.data.selectedTable.url;
  if (table != "") {
    $http.get("http://server:port/api.rsc/" + table + "/$metadata?@json", {headers: {"Authorization":"Basic "  + btoa("MyUser:MyAuthtoken")}})
      .then(function (response) {
          $scope.data.availableColumns = response.data.items[0]["odata:cname"];
          for (i = 0; i < $scope.data.availableColumns.length; i++) {
          $scope.data.availableColumns[i] = { id: i, name: $scope.data.availableColumns[i] };
          }
          });
  }
} 

/*
 * Call to the API Server to get the requested data.We get the data 
 * based on the table selected in the associated HTML select. 
 * Then we create a comma-separated string of the selected columns.
 * 
 * With the table and columns known, we can make the appropriate call
 * to the API Server.Because the driver returns standard OData, the 
 * table data is found in the value field of the response.
 */ 
$scope.getTableData = function () {
  table = $scope.data.selectedTable.url;
  columnsArray = $scope.data.selectedColumns;
  columnString = "";
  for (i = 0; i < columnsArray.length; i++) {
    if (columnString != "") {
      columnString += ",";
    }
    columnString += columnsArray[i].name;
  }

  if (table != "") {
    $http.get("http://server:port/api.rsc/" + table + "?$select=" + columnString, {headers: {"Authorization":"Basic "  + btoa("MyUser:MyAuthtoken")}})
      .then(function (response) { $scope.data.tableData = response.data.value; });
  } else {
    $scope.data.tableData = [];
  }
}     
});
</script>
</body>
</html>

無料トライアルと詳細

Angular で構築されたWeb アプリケーションからAzure Data Lake Storage (またはサポートされている他のデータソースからのデータ)に接続したい場合は、今すぐAPI サーバーの30日間無料トライアルダウンロードしてください。 API のより一般的な情報およびサポートされている他のデータソースについてはAPI サーバーページを参照してください。

トライアル・お問い合わせ

30日間無償トライアルで、CData のリアルタイムデータ連携をフルにお試しいただけます。記事や製品についてのご質問があればお気軽にお問い合わせください。