TripPin パート 4 - データ ソース パス

このマルチパート チュートリアルでは、Power Query 用の新しいデータ ソース拡張機能の作成について説明します。 このチュートリアルは順番に実行することを目的としています。各レッスンは前のレッスンで作成したコネクタに基づいて構築され、コネクタに新しい機能が段階的に追加されます。

このレッスンの内容:

  • コネクタの接続ロジックを単純化する
  • ナビゲーション テーブルのエクスペリエンスを向上させる

このレッスンでは、前のレッスンで作成したコネクタを単純化するために、必要な関数パラメーターを削除し、動的に生成されたナビゲーション テーブルに移行してユーザー エクスペリエンスを向上させます。

資格情報を識別する方法の詳細については、「認証の処理」の「データ ソース パス」セクションを参照してください。

データソースパス

データ ソース関数の呼び出し時、データ ソースの種類データ ソース パスの値に基づいた参照が M エンジンで行われて、評価時に使用する資格情報が識別されます。

前のレッスンでは、どちらも 1 つの Uri.Type パラメーターを使用している 2 つのデータ ソース関数を共有しました。

[DataSource.Kind="TripPin"]
shared TripPin.Feed = Value.ReplaceType(TripPinImpl, type function (url as Uri.Type) as any);

[DataSource.Kind="TripPin", Publish="TripPin.Publish"]
shared TripPin.Contents =  Value.ReplaceType(TripPinNavTable, type function (url as Uri.Type) as any);

関数のいずれかを使用するクエリを初めて実行すると、資格情報の入力を求めるメッセージが表示され、ドロップダウンでパスと認証の種類を選択できます。

Credentials with Paths.

同じクエリを同じパラメーターで再度実行する場合、キャッシュされた資格情報を M エンジンで特定できるため、資格情の入力メッセージは表示されません。 関数の url 引数を変更して基本パスが一致しなくなると、新しいパスについての新しい資格情報入力メッセージが表示されます。

キャッシュされた資格情報は、[M Query Output]\(M クエリ出力\) ウィンドウの [資格情報] タブで確認できます。

Credentials tab.

関数のパラメーターを変更すると、変更の種類によっては、資格情報エラーが発生する可能性があります。

コネクタの簡素化

次に、データ ソース関数 (TripPin.Contents) のパラメーターを削除してコネクタを単純化します。 また、TripPin.Feedshared 修飾子を削除したうえで、内部専用関数のままにします。

Power Query の設計思想の 1 つは、最初のデータ ソース ダイアログをできるだけ単純なものに保つことです。 可能であれば、接続ダイアログではなく、ナビゲーターのレベルでユーザーに選択肢を提供する必要があります。 ユーザーが指定した値をプログラムによって特定できる場合、それを関数パラメーターではなく、ナビゲーション テーブルの最上位レベルとして追加することを検討してください。

たとえば、リレーショナル データベースに接続する場合は、サーバー、データベース、テーブルの名前が必要になることが考えられます。 接続先のサーバーを特定し、資格情報が提供されたら、データベースの API を使用してデータベースの一覧を取得し、各データベース内に含まれているテーブルの一覧を取得できます。 この場合、最初の接続ダイアログをできるだけ単純にするために、サーバー名のみを必須パラメーターにする必要があります。DatabaseTable はナビゲーション テーブルのレベルになります。

TripPin サービスには固定の URL エンドポイントがあるため、ユーザーに値の入力を求める必要はありません。 関数から url パラメーターを削除し、コネクタで BaseUrl 変数を定義します。

BaseUrl = "https://services.odata.org/v4/TripPinService/";

[DataSource.Kind="TripPin", Publish="TripPin.Publish"]
shared TripPin.Contents = () => TripPinNavTable(BaseUrl) as table;

TripPin.Feed 関数は、残しますが共有にはせず、データ ソースの種類に関連付けずに、宣言を単純化します。 これ以降は、このセクションのドキュメント内で内部的に使用するだけにします。

TripPin.Feed = (url as text) =>
    let
        source = Web.Contents(url, [ Headers = DefaultRequestHeaders ]),
        json = Json.Document(source)
    in
        json;

TripPin.query.pq ファイル内の TripPin.Contents() 呼び出しを更新し、Visual Studio で実行すると、新しい資格情報の入力メッセージが表示されます。 現在、単一のデータ ソース パス値、TripPin があることに注意してください。

Credentials with no path.

ナビゲーションテーブルの改善

最初のチュートリアルでは、組み込みの OData 関数を使用して TripPin サービスに接続しました。 これにより、自分でコードを追加することなく、TripPin サービス ドキュメントに基づいた見栄えの良いナビゲーション テーブルを作成できました。 複雑な作業は、自分の代わりに OData 関数が自動的に実行してくれました。 使用しているのは OData.Feed ではなく "間に合わせ" の Web.Contents であるため、このナビゲーション テーブルを自分で再作成する必要があります。

OData Navigator.

次の変更を行います。

  1. ナビゲーション テーブルに表示する項目の一覧を定義する
  2. エンティティ固有の関数 (GetAirlineTablesGetAirportsTable) を排除する

リストからナビゲーションテーブルを生成する

ナビゲーション テーブルに公開するエンティティを一覧表示し、それらにアクセスするための適切な URL を作成します。 すべてのエンティティが同じルート パスにあるため、これらの URL を動的に構築できます。

例を単純化するために、M でテーブルとして公開される 3 つのエンティティ セット (Airlines、Airports、People) のみを公開し、レコードとして公開されるシングルトン (Me) をスキップします。 関数の追加は、後のレッスンで行います。

RootEntities = {
    "Airlines",
    "Airports",
    "People"
};

次に、TripPinNavTable 関数を更新して、一度に 1 列ずつテーブルを作成します。 各エンティティの [Data] 列は、エンティティへの完全な URL を指定して TripPin.Feed を呼び出すことによって取得します。

TripPinNavTable = (url as text) as table =>
    let
        entitiesAsTable = Table.FromList(RootEntities, Splitter.SplitByNothing()),
        rename = Table.RenameColumns(entitiesAsTable, {{"Column1", "Name"}}),
        // Add Data as a calculated column
        withData = Table.AddColumn(rename, "Data", each TripPin.Feed(Uri.Combine(url, [Name])), Uri.Type),
        // Add ItemKind and ItemName as fixed text values
        withItemKind = Table.AddColumn(withData, "ItemKind", each "Table", type text),
        withItemName = Table.AddColumn(withItemKind, "ItemName", each "Table", type text),
        // Indicate that the node should not be expandable
        withIsLeaf = Table.AddColumn(withItemName, "IsLeaf", each true, type logical),
        // Generate the nav table
        navTable = Table.ToNavigationTable(withIsLeaf, {"Name"}, "Name", "Data", "ItemKind", "ItemName", "IsLeaf")
    in
        navTable;

URL のパスを動的に作成する場合は、スラッシュ (/) の位置について明確に理解しておく必要があります。 Uri.Combine でパスを組み合わせるときは、次の規則が使用されることに注意してください。

  • relativeUri パラメーターが / で始まっている場合、baseUri パラメーターのパス全体が置換されます
  • relativeUri パラメーターが / で始まって いない 場合、baseUri が / で終わっていれば、パスは付加されます
  • relativeUri パラメータが で始まらず、baseUriが / で終わらない場合、パスの最後のセグメントが置き換えられます。

次の図は、この例を示しています。

Uri.Combine example.

エンティティ固有の関数を削除する

コネクタの保守を容易にするために、前のレッスンで使用したエンティティ固有の書式設定関数 GetAirlineTablesGetAirportsTable を削除します。 その代わりに TripPin.Feed を更新し、すべてのエンティティに対して機能する方法で JSON 応答を処理します。 具体的には、返された OData JSON ペイロードの value フィールドを取得し、レコードの一覧からテーブルに変換します。

TripPin.Feed = (url as text) =>
    let
        source = Web.Contents(url, [ Headers = DefaultRequestHeaders ]),
        json = Json.Document(source),
        // The response is a JSON record - the data we want is a list of records in the "value" field
        value = json[value],
        asTable = Table.FromList(value, Splitter.SplitByNothing()),
        // expand all columns from the record
        fields = Record.FieldNames(Table.FirstValue(asTable, [Empty = null])),
        expandAll = Table.ExpandRecordColumn(asTable, "Column1", fields)
    in
        expandAll;

Note

汎用的な方法を使用してエンティティを処理することの欠点は、エンティティの見栄えの良い書式情報と型情報が失われることです。 このチュートリアルの後のセクションでは、REST API 呼び出しにスキーマを適用する方法を示します。

まとめ

このチュートリアルでは、データ ソース パスの値を修正し、ナビゲーション テーブルの形式をより柔軟なものに移行することで、コネクタをクリーンアップし、単純化しました。 これらの手順を完了 (または、このディレクトリのサンプル コードを使用) すると、Power BI Desktop に TripPin.Contents 関数からナビゲーション テーブルが返されます。

Navigator.

次のステップ

TripPin パート 5 - ページング