Udostępnij za pośrednictwem


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:

Żądania OData programu Fiddler.

  • /Me— rzeczywisty adres URL, którego żądasz.
  • /$metadata— wywołanie wykonywane automatycznie przez OData.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ło 204 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.

Wyniki OData.

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.Feedelementu , 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.

Wyświetl wyniki.

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.

Sformatowane linie lotnicze.

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").

Sformatowane 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ść.

Zapory.

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.

Prywatność.

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.

FakeNav.

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.

Następne kroki

TripPin — część 3 — tabele nawigacji