TripPin — część 2 — łącznik danych dla usługi REST
Ten wieloczęściowy samouczek obejmuje tworzenie nowego rozszerzenia źródła danych dla dodatku Power Query. Samouczek ma być wykonywany sekwencyjnie — każda lekcja opiera się na łączniku utworzonym w poprzednich lekcjach, przyrostowo dodając nowe możliwości do łącznika.
W tej lekcji wykonasz następujące lekcji:
- Tworzenie funkcji podstawowej, która wywołuje interfejs API REST przy użyciu biblioteki Web.Contents
- Dowiedz się, jak ustawiać nagłówki żądań i przetwarzać odpowiedź w formacie JSON
- Używanie programu Power BI Desktop do rozmieszczania odpowiedzi w formacie przyjaznym dla użytkownika
Ta lekcja konwertuje łącznik OData dla usługi TripPin (utworzony w poprzedniej lekcji) na łącznik podobny do utworzonego dla dowolnego interfejsu API RESTful. OData to interfejs API RESTful, ale jeden ze stałym zestawem konwencji. Zaletą usługi OData jest zapewnienie schematu, protokołu pobierania danych i standardowego języka zapytań. Korzystanie z usługi OData.Feed będzie wymagało od nas utworzenia tych możliwości w łączniku.
Podsumowanie łącznika OData
Przed usunięciem funkcji OData z łącznika wykonajmy szybką recenzję tego, co obecnie robi (głównie za kulisami), aby pobrać dane z usługi.
Otwórz projekt rozszerzenia TripPin z części 1 w programie Visual Studio Code. Otwórz plik Query i wklej następujące zapytanie:
TripPin.Feed("https://services.odata.org/v4/TripPinService/Me")
Otwórz program Fiddler, a następnie oceń bieżący plik Power Query w programie Visual Studio Code.
W programie Fiddler istnieją trzy żądania do serwera:
/Me
— rzeczywisty adres URL, którego żądasz./$metadata
— wywołanie wykonywane automatycznie przezOData.Feed
funkcję w celu określenia schematu i typu informacji o odpowiedzi./Me/BestFriend
— jedno z pól, które było (z niecierpliwością) ściągnięte podczas wyświetlania /Me singleton. W takim przypadku wywołanie spowodowało204 No Content
powstanie stanu.
Ocena M jest głównie leniwa. W większości przypadków wartości danych są pobierane/ściągane tylko wtedy, gdy są potrzebne. Istnieją scenariusze (takie jak /Me/BestFriend), w których wartość jest ciągnięta z niecierpliwością. Zwykle występuje to, gdy informacje o typie są potrzebne dla elementu członkowskiego, a aparat nie ma innego sposobu na określenie typu niż pobranie wartości i sprawdzenie jej. Tworzenie rzeczy leniwych (czyli unikanie chętnych ściągnięcia) jest jednym z kluczowych aspektów tworzenia łącznika M wydajne.
Zwróć uwagę na nagłówki żądań, które zostały wysłane wraz z żądaniami i formatem JSON odpowiedzi żądania /Me.
{
"@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
}
Po zakończeniu oceny zapytania okno wyników PQTest powinno wyświetlić wartość Rekord dla pojedynczego pliku Me.
Jeśli porównasz pola w oknie danych wyjściowych z polami zwróconymi w nieprzetworzonej odpowiedzi JSON, zauważysz niezgodność. Wynik zapytania zawiera inne pola (Friends
, Trips
, GetFriendsTrips
), które nie są wyświetlane nigdzie w odpowiedzi JSON. Funkcja OData.Feed automatycznie dołącza te pola do rekordu na podstawie schematu zwróconego przez $metadata. Jest to dobry przykład sposobu rozszerzania i/lub ponownego formatowania odpowiedzi z usługi w celu zapewnienia lepszego środowiska użytkownika.
Tworzenie podstawowego łącznika REST
Teraz dodasz nową wyeksportowaną funkcję do łącznika, która wywołuje funkcję Web.Contents.
Aby można było pomyślnie wysyłać żądania internetowe do usługi OData, należy jednak ustawić niektóre standardowe nagłówki OData. W tym celu zdefiniujesz wspólny zestaw nagłówków jako nową zmienną w łączniku:
DefaultRequestHeaders = [
#"Accept" = "application/json;odata.metadata=minimal", // column name and values only
#"OData-MaxVersion" = "4.0" // we only support v4
];
Możesz zmienić implementację TripPin.Feed
funkcji, aby zamiast używać OData.Feed
elementu , używa elementu Web.Contents do utworzenia żądania internetowego i analizuje wynik jako dokument JSON.
TripPinImpl = (url as text) =>
let
source = Web.Contents(url, [ Headers = DefaultRequestHeaders ]),
json = Json.Document(source)
in
json;
Pamiętaj, aby skompilować łącznik po wprowadzeniu zmian w pliku łącznika. Następnie możesz ocenić plik zapytania (TripPin.query.pq). Wynik rekordu /Me jest teraz podobny do nieprzetworzonego kodu JSON, który został wyświetlony w żądaniu programu Fiddler.
Jeśli oglądasz program Fiddler podczas uruchamiania nowej funkcji, zauważysz również, że ocena wykonuje teraz pojedyncze żądanie internetowe, a nie trzy. Gratulacje — osiągnięto 300% wzrost wydajności! Utraciliśmy wszystkie informacje o typie i schemacie, ale nie trzeba jeszcze skupiać się na tej części.
Zaktualizuj zapytanie, aby uzyskać dostęp do niektórych jednostek/tabel TripPin, takich jak:
https://services.odata.org/v4/TripPinService/Airlines
https://services.odata.org/v4/TripPinService/Airports
https://services.odata.org/v4/TripPinService/Me/Trips
Zauważysz, że ścieżki, które były używane do zwracania ładnie sformatowanych tabel, zwracają teraz pole "value" najwyższego poziomu z osadzonym polem [List]. Aby można było korzystać ze scenariuszy użycia użytkowników końcowych, należy wykonać pewne przekształcenia w wyniku.
Przekształcenia tworzenia w dodatku Power Query
Chociaż możliwe jest ręczne tworzenie przekształceń języka M, większość osób woli używać dodatku Power Query do kształtowania danych. Otworzysz rozszerzenie w programie Power BI Desktop i użyjesz go do projektowania zapytań w celu przekształcenia danych wyjściowych w bardziej przyjazny dla użytkownika format. Ponownie skompiluj rozwiązanie, skopiuj nowy plik rozszerzenia do katalogu Custom Data Połączenie ors i uruchom ponownie program Power BI Desktop.
Uruchom nowe puste zapytanie i wklej następujące polecenie na pasku formuły:
= TripPin.Feed("https://services.odata.org/v4/TripPinService/Airlines")
Pamiętaj, aby uwzględnić znak = .
Manipuluj danymi wyjściowymi, dopóki nie będzie wyglądało to jak oryginalne źródło danych OData — tabela z dwiema kolumnami: AirlineCode i Name.
Wynikowe zapytanie powinno wyglądać mniej więcej tak:
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
Nadaj kwerendzie nazwę ("Airlines").
Utwórz nowe puste zapytanie. Tym razem użyj TripPin.Feed
funkcji , aby uzyskać dostęp do jednostki /Airports. Zastosuj przekształcenia, dopóki nie uzyskasz czegoś podobnego do udziału pokazanego poniżej. Pasujące zapytanie można również znaleźć poniżej — nadaj tej kwerendzie nazwę ("Lotniska").
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"
Ten proces można powtórzyć, aby uzyskać więcej ścieżek w ramach usługi. Gdy wszystko będzie gotowe, przejdź do następnego kroku tworzenia (pozornej) tabeli nawigacyjnej.
Symulowanie tabeli nawigacji
Teraz utworzysz tabelę (przy użyciu kodu M), która przedstawia ładnie sformatowane jednostki TripPin.
Uruchom nowe puste zapytanie i wyświetl Edytor zaawansowany.
Wklej następujące zapytanie:
let
source = #table({"Name", "Data"}, {
{ "Airlines", Airlines },
{ "Airports", Airports }
})
in
source
Jeśli nie ustawiono ustawienia Poziomy prywatności na wartość "Zawsze ignoruj ustawienia poziomu prywatności" (znane również jako "Szybkie łączenie"), zostanie wyświetlony monit o prywatność.
Monity o prywatność są wyświetlane, gdy łączysz dane z wielu źródeł i nie określono jeszcze poziomu prywatności dla co najmniej jednego źródła. Wybierz przycisk Kontynuuj i ustaw poziom prywatności najwyższego źródła na Publiczny.
Wybierz pozycję Zapisz , a tabela zostanie wyświetlona. Chociaż nie jest to jeszcze tabela nawigacji, zapewnia ona podstawowe funkcje, które należy przekształcić w jedną w kolejnej lekcji.
Sprawdzanie kombinacji danych nie występuje podczas uzyskiwania dostępu do wielu źródeł danych z poziomu rozszerzenia. Ponieważ wszystkie wywołania źródła danych wykonywane z poziomu rozszerzenia dziedziczą ten sam kontekst autoryzacji, zakłada się, że są one "bezpieczne", aby połączyć. Rozszerzenie będzie zawsze traktowane jako pojedyncze źródło danych, jeśli chodzi o reguły kombinacji danych. Użytkownicy nadal będą otrzymywać regularne monity o prywatność podczas łączenia źródła z innymi źródłami języka M.
Jeśli uruchomisz program Fiddler i wybierz przycisk Odśwież podgląd w Edytor Power Query, zanotuj oddzielne żądania internetowe dla każdego elementu w tabeli nawigacji. Oznacza to, że występuje chętna ocena, która nie jest idealna podczas tworzenia tabel nawigacji z wieloma elementami. Kolejne lekcje pokazują, jak utworzyć odpowiednią tabelę nawigacji, która obsługuje leniwą ocenę.
Podsumowanie
W tej lekcji pokazano, jak utworzyć prosty łącznik dla usługi REST. W takim przypadku istniejące rozszerzenie OData zostało przekształcone w standardowe rozszerzenie REST (przy użyciu biblioteki Web.Contents), ale te same pojęcia mają zastosowanie, jeśli tworzysz nowe rozszerzenie od podstaw.
W następnej lekcji wykonasz zapytania utworzone w tej lekcji przy użyciu programu Power BI Desktop i przekształcisz je w prawdziwą tabelę nawigacji w rozszerzeniu.