Share via


TripPin 第 2 部分 - REST 服務的資料連線器

此多部分教學課程涵蓋如何建立 Power Query 的新資料來源延伸模組。 本教學課程旨在循序完成,每個課程都是以先前課程中建立的連接器為基礎,以累加方式將新功能新增至您的連接器。

在本課程中,您將會:

這一課會將 TripPin 服務的 OData 型連接器 (在上一課 建立)轉換成類似您為任何 RESTful API 建立的連接器。 OData 是 RESTful API,但有一組固定的慣例。 OData 的優點是其提供架構、資料擷取通訊協定和標準查詢語言。 取下 OData.Feed 的使用 需要我們自行在連接器中建置這些功能。

OData 連接器的回顧

在您從連接器移除 OData 函式之前,讓我們快速檢閱它目前執行的功能(大部分在幕後),以從服務擷取資料。

Visual Studio 中的第 1 部分開啟 TripPin 連接器專案。 開啟 [查詢] 檔案並貼上下列查詢:

TripPin.Feed("https://services.odata.org/v4/TripPinService/Me")

開啟 Fiddler,然後選取 Visual Studio 中的 [開始] 按鈕。

在 Fiddler 中,您會看到三個伺服器要求:

Fiddler OData requests.

  • /Me—您要要求的實際 URL。
  • /$metadata—函式自動發出的 OData.Feed 呼叫,以判斷回應的架構和類型資訊。
  • /Me/BestFriend—當您列出 /Me 單一時,會提取其中一個(急切地)的欄位。 在此情況下,呼叫會產生 204 No Content 狀態。

M 評估大多是懶惰的。 在大部分情況下,資料值只會在需要時擷取/提取。 在某些情況下(例如 /Me/BestFriend 案例)會急切地提取值。 當成員需要型別資訊時,通常會發生這種情況,而且引擎沒有比擷取值並檢查它別別的方法。 讓事情懶惰(也就是避免急切的提取)是使 M 連接器高效能的關鍵層面之一。

請注意已連同要求和 /Me 要求回應的 JSON 格式一起傳送的要求標頭。

{
  "@odata.context": "https://services.odata.org/v4/TripPinService/$metadata#Me",
  "UserName": "aprilcline",
  "FirstName": "April",
  "LastName": "Cline",
  "MiddleName": null,
  "Gender": "Female",
  "Age": null,
  "Emails": [ "April@example.com", "April@contoso.com" ],
  "FavoriteFeature": "Feature1",
  "Features": [ ],
  "AddressInfo": [
    {
      "Address": "P.O. Box 555",
      "City": {
        "Name": "Lander",
        "CountryRegion": "United States",
        "Region": "WY"
      }
    }
  ],
  "HomeAddress": null
}

當查詢完成評估時,[M 查詢輸出] 視窗應該會顯示 Me singleton 的 [記錄] 值。

OData results.

如果您比較輸出視窗中的欄位與原始 JSON 回應中傳回的欄位,您會發現不符。 查詢結果具有 JSON 回應中未出現在任何地方的其他欄位 ( FriendsTripsGetFriendsTrips ) 。 OData.Feed 函式會根據$metadata傳回的架構,自動將這些欄位附加至記錄。 這是連接器如何增強和/或重新格式化服務的回應,以提供更佳使用者體驗的良好範例。

建立基本 REST 連接器

您現在會將新的匯出函式新增至呼叫 Web.Contents 的 連接器。

不過,若要能夠成功對 OData 服務提出 Web 要求,您必須設定一些 標準 OData 標頭 。 您會在連接器中將一組常見的標頭定義為新的變數,以執行此動作:

DefaultRequestHeaders = [
    #"Accept" = "application/json;odata.metadata=minimal",  // column name and values only
    #"OData-MaxVersion" = "4.0"                             // we only support v4
];

您將變更函式的實作 TripPin.Feed ,使其不使用 OData.Feed ,它會使用 Web.Contents 提出 Web 要求,並將結果剖析為 JSON 檔。

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

您現在可以使用查詢檔案在 Visual Studio 中測試此專案。 /Me 記錄的結果現在類似于您在 Fiddler 要求中看到的原始 JSON。

如果您在執行新函式時監看 Fiddler,您也會注意到評估現在會提出單一 Web 要求,而不是三個。 恭喜您—您已達到 300% 的效能提升! 當然,您現在已遺失所有類型和架構資訊,但目前不需要專注于該部分。

更新您的查詢以存取某些 TripPin 實體/資料表,例如:

  • https://services.odata.org/v4/TripPinService/Airlines
  • https://services.odata.org/v4/TripPinService/Airports
  • https://services.odata.org/v4/TripPinService/Me/Trips

您會發現,用來傳回良好格式資料表的路徑現在會傳回具有內嵌 [List] 的最上層 「value」 欄位。 您必須對結果執行一些轉換,才能讓 Power BI 案例使用。

List results.

在 Power Query 中撰寫轉換

雖然您當然可以手動撰寫 M 轉換,但大多數人偏好使用 Power Query 來塑造其資料。 您將在 Power BI Desktop 中開啟延伸模組,並用它來設計查詢,將輸出轉換成更方便使用的格式。 重建解決方案、將新的延伸模組檔案複製到您的自訂資料連線ors 目錄,然後重新開機 Power BI Desktop。

啟動新的空白查詢,並將下列內容貼到公式列中:

= TripPin.Feed("https://services.odata.org/v4/TripPinService/Airlines")

請務必包含 = 符號。

操作輸出,直到它看起來像原始的 OData 摘要—包含兩個數據行的資料表:AirlineCode 和 Name。

Formatted airlines.

產生的查詢看起來應該像這樣:

let
    Source = TripPin.Feed("https://services.odata.org/v4/TripPinService/Airlines"),
    value = Source[value],
    toTable = Table.FromList(value, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    expand = Table.ExpandRecordColumn(toTable, "Column1", {"AirlineCode", "Name"}, {"AirlineCode", "Name"})
in
    expand

為查詢指定名稱 (「Airlines」 )。

建立新的空白查詢。 這次,請使用 函 TripPin.Feed 式來存取 /Airports 實體。 套用轉換,直到您得到類似如下所示的共用為止。 您也可以在下方找到相符的查詢,也提供此查詢的名稱(「Airports」)。

Formatted airports.

let
    Source = TripPin.Feed("https://services.odata.org/v4/TripPinService/Airports"),
    value = Source[value],
    #"Converted to Table" = Table.FromList(value, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table", "Column1", {"Name", "IcaoCode", "IataCode", "Location"}, {"Name", "IcaoCode", "IataCode", "Location"}),
    #"Expanded Location" = Table.ExpandRecordColumn(#"Expanded Column1", "Location", {"Address", "Loc", "City"}, {"Address", "Loc", "City"}),
    #"Expanded City" = Table.ExpandRecordColumn(#"Expanded Location", "City", {"Name", "CountryRegion", "Region"}, {"Name.1", "CountryRegion", "Region"}),
    #"Renamed Columns" = Table.RenameColumns(#"Expanded City",{{"Name.1", "City"}}),
    #"Expanded Loc" = Table.ExpandRecordColumn(#"Renamed Columns", "Loc", {"coordinates"}, {"coordinates"}),
    #"Added Custom" = Table.AddColumn(#"Expanded Loc", "Latitude", each [coordinates]{1}),
    #"Added Custom1" = Table.AddColumn(#"Added Custom", "Longitude", each [coordinates]{0}),
    #"Removed Columns" = Table.RemoveColumns(#"Added Custom1",{"coordinates"}),
    #"Changed Type" = Table.TransformColumnTypes(#"Removed Columns",{{"Name", type text}, {"IcaoCode", type text}, {"IataCode", type text}, {"Address", type text}, {"City", type text}, {"CountryRegion", type text}, {"Region", type text}, {"Latitude", type number}, {"Longitude", type number}})
in
    #"Changed Type"

您可以針對服務下的其他路徑重複此程式。 準備好之後,請移至建立 (模擬) 流覽資料表的下一個步驟。

模擬流覽資料表

現在,您將建置一個資料表(使用 M 程式碼),以呈現您格式良好的 TripPin 實體。

啟動新的空白查詢並啟動進階編輯器。

貼上下列查詢:

let
    source = #table({"Name", "Data"}, {
        { "Airlines", Airlines },
        { "Airports", Airports }
    })
in
    source

如果您尚未將 [隱私權等級] 設定設為 [一律忽略隱私權等級設定] (也稱為「快速合併」),您會看到隱私權提示。

Firewall.

當您合併多個來源的資料,但尚未指定來源的隱私權等級時,會出現隱私權提示。 選取 [ 繼續] 按鈕,並將最上層來源的隱私權層級設定為 [公用 ]。

Privacy.

選取 [ 儲存] ,您的資料表隨即出現。 雖然這還不是導覽資料表,但它提供您在後續課程中將其轉換成其中一項所需的基本功能。

FakeNav.

從延伸模組記憶體取多個資料來源時,不會進行資料組合檢查。 由於延伸模組內發出的所有資料來源呼叫都會繼承相同的授權內容,因此假設它們是「安全」合併的。 在資料組合規則方面,您的延伸模組一律會被視為單一資料來源。 將來源與其他 M 來源結合時,使用者仍會收到一般隱私權提示。

如果您執行 Fiddler 並按一下 查詢編輯器中的 [重新整理預覽 ] 按鈕,您會注意到導覽資料表中每個專案的個別 Web 要求。 這表示正在進行積極評估,這在建置具有許多元素的導覽資料表時並不理想。 後續的課程將示範如何建置支援延遲評估的適當流覽資料表。

推論

本課程說明如何為 REST 服務建置簡單的連接器。 在此情況下,您已將現有的 OData 延伸模組轉換成標準 REST 延伸模組(使用 Web.Contents ),但如果您從頭開始建立新的擴充功能,則適用相同的概念。

在下一課中,您將採用使用 Power BI Desktop 在本課程中建立的查詢,並將其轉換成延伸模組內真正的導覽資料表。

下一步

TripPin 第 3 部分 - 導覽表格