TripPin 第 2 部分 - REST 服務的資料連線器
此多部分教學課程涵蓋如何建立 Power Query 的新資料來源延伸模組。 本教學課程旨在循序完成,每個課程都是以先前課程中建立的連接器為基礎,以累加方式將新功能新增至您的連接器。
在本課程中,您將會:
- 使用 Web.Contents 建立呼叫 REST API 的基底函式
- 瞭解如何設定要求標頭並處理 JSON 回應
- 使用 Power BI Desktop 將回應擷取成使用者易記格式
這一課會將 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 中,您會看到三個伺服器要求:
/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 的 [記錄] 值。
如果您比較輸出視窗中的欄位與原始 JSON 回應中傳回的欄位,您會發現不符。 查詢結果具有 JSON 回應中未出現在任何地方的其他欄位 ( Friends
、 Trips
GetFriendsTrips
) 。 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 案例使用。
在 Power Query 中撰寫轉換
雖然您當然可以手動撰寫 M 轉換,但大多數人偏好使用 Power Query 來塑造其資料。 您將在 Power BI Desktop 中開啟延伸模組,並用它來設計查詢,將輸出轉換成更方便使用的格式。 重建解決方案、將新的延伸模組檔案複製到您的自訂資料連線ors 目錄,然後重新開機 Power BI Desktop。
啟動新的空白查詢,並將下列內容貼到公式列中:
= TripPin.Feed("https://services.odata.org/v4/TripPinService/Airlines")
請務必包含 = 符號。
操作輸出,直到它看起來像原始的 OData 摘要—包含兩個數據行的資料表:AirlineCode 和 Name。
產生的查詢看起來應該像這樣:
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」)。
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
如果您尚未將 [隱私權等級] 設定設為 [一律忽略隱私權等級設定] (也稱為「快速合併」),您會看到隱私權提示。
當您合併多個來源的資料,但尚未指定來源的隱私權等級時,會出現隱私權提示。 選取 [ 繼續] 按鈕,並將最上層來源的隱私權層級設定為 [公用 ]。
選取 [ 儲存] ,您的資料表隨即出現。 雖然這還不是導覽資料表,但它提供您在後續課程中將其轉換成其中一項所需的基本功能。
從延伸模組記憶體取多個資料來源時,不會進行資料組合檢查。 由於延伸模組內發出的所有資料來源呼叫都會繼承相同的授權內容,因此假設它們是「安全」合併的。 在資料組合規則方面,您的延伸模組一律會被視為單一資料來源。 將來源與其他 M 來源結合時,使用者仍會收到一般隱私權提示。
如果您執行 Fiddler 並按一下 查詢編輯器中的 [重新整理預覽 ] 按鈕,您會注意到導覽資料表中每個專案的個別 Web 要求。 這表示正在進行積極評估,這在建置具有許多元素的導覽資料表時並不理想。 後續的課程將示範如何建置支援延遲評估的適當流覽資料表。
推論
本課程說明如何為 REST 服務建置簡單的連接器。 在此情況下,您已將現有的 OData 延伸模組轉換成標準 REST 延伸模組(使用 Web.Contents ),但如果您從頭開始建立新的擴充功能,則適用相同的概念。
在下一課中,您將採用使用 Power BI Desktop 在本課程中建立的查詢,並將其轉換成延伸模組內真正的導覽資料表。
下一步
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應