TripPin parte 2 - Connettore dati per un servizio REST
Questa esercitazione in più parti illustra la creazione di una nuova estensione dell'origine dati per Power Query. L'esercitazione è destinata a essere eseguita in sequenza: ogni lezione si basa sul connettore creato nelle lezioni precedenti, aggiungendo in modo incrementale nuove funzionalità al connettore.
In questa lezione verranno illustrate le procedure seguenti:
- Creare una funzione di base che chiama a un'API REST usando Web.Contents
- Informazioni su come impostare le intestazioni della richiesta ed elaborare una risposta JSON
- Usare Power BI Desktop per suddividere la risposta in un formato descrittivo
Questa lezione converte il connettore basato su OData per il servizio TripPin (creato nella lezione precedente) in un connettore simile a quello creato per qualsiasi API RESTful. OData è un'API RESTful, ma una con un set fisso di convenzioni. Il vantaggio di OData è che fornisce uno schema, un protocollo di recupero dei dati e un linguaggio di query standard. L'uso di OData.Feed richiederà di creare queste funzionalità nel connettore.
Riepilogo del connettore OData
Prima di rimuovere le funzioni OData dal connettore, è possibile esaminare rapidamente le operazioni attualmente eseguite (principalmente in background) per recuperare i dati dal servizio.
Aprire il progetto di estensione TripPin dalla Parte 1 in Visual Studio Code. Aprire il file di query e incollarlo nella query seguente:
TripPin.Feed("https://services.odata.org/v4/TripPinService/Me")
Aprire Fiddler e quindi valutare il file di Power Query corrente in Visual Studio Code.
In Fiddler sono presenti tre richieste al server:
/Me
: l'URL effettivo richiesto./$metadata
: una chiamata eseguita automaticamente dallaOData.Feed
funzione per determinare le informazioni sullo schema e sul tipo sulla risposta./Me/BestFriend
— uno dei campi che era (eagerly) tirato quando hai elencato il singleton /Me. In questo caso, la chiamata ha generato uno204 No Content
stato.
La valutazione M è per lo più differita. Nella maggior parte dei casi, i valori dei dati vengono recuperati/estratti solo quando sono necessari. Esistono scenari (ad esempio il caso /Me/BestFriend) in cui un valore viene estratto in modo eager. Ciò tende a verificarsi quando sono necessarie informazioni sul tipo per un membro e il motore non ha altro modo per determinare il tipo che per recuperare il valore e controllarlo. Rendere le cose lazy (ovvero evitare pull eager) è uno degli aspetti chiave per rendere efficiente un connettore M.
Si notino le intestazioni della richiesta inviate insieme alle richieste e al formato JSON della risposta della richiesta /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
}
Al termine della valutazione della query, la finestra dei risultati PQTest dovrebbe visualizzare il valore Record per il singleton Me.
Se si confrontano i campi nella finestra di output con i campi restituiti nella risposta JSON non elaborata, si noterà una mancata corrispondenza. Il risultato della query include altri campi (Friends
, Trips
, GetFriendsTrips
) che non vengono visualizzati in nessun punto della risposta JSON. La funzione OData.Feed accodò automaticamente questi campi al record in base allo schema restituito da $metadata. Questo è un buon esempio di come un connettore potrebbe aumentare e/o riformattare la risposta dal servizio per offrire un'esperienza utente migliore.
Creazione di un connettore REST di base
A questo punto si aggiungerà una nuova funzione esportata al connettore che chiama Web.Contents.
Per poter effettuare richieste Web riuscite al servizio OData, tuttavia, è necessario impostare alcune intestazioni OData standard. A tale scopo, definire un set comune di intestazioni come nuova variabile nel connettore:
DefaultRequestHeaders = [
#"Accept" = "application/json;odata.metadata=minimal", // column name and values only
#"OData-MaxVersion" = "4.0" // we only support v4
];
Modificare l'implementazione della TripPin.Feed
funzione in modo che, anziché usare OData.Feed
, usi Web.Contents per effettuare una richiesta Web e analizzi il risultato come documento JSON.
TripPinImpl = (url as text) =>
let
source = Web.Contents(url, [ Headers = DefaultRequestHeaders ]),
json = Json.Document(source)
in
json;
Ricordarsi di compilare il connettore ora che sono state apportate modifiche al file del connettore. È quindi possibile valutare il file di query (TripPin.query.pq). Il risultato del record /Me ora è simile al codice JSON non elaborato visualizzato nella richiesta Fiddler.
Se si osserva Fiddler quando si esegue la nuova funzione, si noterà anche che la valutazione effettua ora una singola richiesta Web, anziché tre. Congratulazioni: si è ottenuto un aumento delle prestazioni del 300%. Ora si sono perse tutte le informazioni sul tipo e sullo schema, ma non è ancora necessario concentrarsi su tale parte.
Aggiornare la query per accedere ad alcune delle entità/tabelle TripPin, ad esempio:
https://services.odata.org/v4/TripPinService/Airlines
https://services.odata.org/v4/TripPinService/Airports
https://services.odata.org/v4/TripPinService/Me/Trips
Si noterà che i percorsi usati per restituire tabelle formattate in modo corretto restituiscono ora un campo "valore" di primo livello con un [Elenco] incorporato. È necessario eseguire alcune trasformazioni sul risultato per renderla utilizzabile per gli scenari di utilizzo degli utenti finali.
Trasformazioni di creazione in Power Query
Sebbene sia possibile creare le trasformazioni M a mano, la maggior parte delle persone preferisce usare Power Query per modellare i dati. Si aprirà l'estensione in Power BI Desktop e la si userà per progettare query per trasformare l'output in un formato più descrittivo. Ricompilare la soluzione, copiare il nuovo file di estensione nella directory Custom Data Connessione ors e riavviare Power BI Desktop.
Avviare una nuova query vuota e incollare quanto segue nella barra della formula:
= TripPin.Feed("https://services.odata.org/v4/TripPinService/Airlines")
Assicurarsi di includere il segno = .
Modificare l'output fino a quando non sarà simile al feed OData originale, ovvero una tabella con due colonne: AirlineCode e Name.
La query risultante dovrebbe avere un aspetto simile al seguente:
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
Assegnare alla query un nome ("Airlines").
Creare una nuova query vuota. Questa volta, usare la TripPin.Feed
funzione per accedere all'entità /Airports. Applicare le trasformazioni fino a ottenere un risultato simile alla condivisione illustrata di seguito. La query corrispondente è disponibile anche di seguito. assegnare anche a questa query un nome ("Aeroporti").
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"
È possibile ripetere questo processo per altri percorsi nel servizio. Una volta pronti, passare al passaggio successivo della creazione di una tabella di spostamento (fittizia).
Simulazione di una tabella di spostamento
Ora si creerà una tabella (usando codice M) che presenta le entità TripPin formattate in modo corretto.
Avviare una nuova query vuota e visualizzare il Editor avanzato.
Incollare la query seguente:
let
source = #table({"Name", "Data"}, {
{ "Airlines", Airlines },
{ "Airports", Airports }
})
in
source
Se l'impostazione Livelli di privacy non è stata impostata su "Ignora sempre le impostazioni del livello di privacy" (nota anche come "Combinazione rapida") verrà visualizzata una richiesta di privacy.
Le richieste di privacy vengono visualizzate quando si combinano dati da più origini e non è stato ancora specificato un livello di privacy per una o più origini. Selezionare il pulsante Continua e impostare il livello di privacy dell'origine principale su Pubblico.
Selezionare Salva e verrà visualizzata la tabella. Anche se non si tratta ancora di una tabella di spostamento, fornisce la funzionalità di base necessaria per trasformarla in una lezione successiva.
I controlli delle combinazioni di dati non si verificano quando si accede a più origini dati dall'interno di un'estensione. Poiché tutte le chiamate all'origine dati effettuate dall'interno dell'estensione ereditano lo stesso contesto di autorizzazione, si presuppone che siano "sicure" da combinare. L'estensione verrà sempre considerata come una singola origine dati quando si tratta di regole di combinazione di dati. Gli utenti riceveranno comunque le normali richieste di privacy quando si combina l'origine con altre origini M.
Se si esegue Fiddler e si seleziona il pulsante Aggiorna anteprima nella Editor di query, prendere nota delle richieste Web separate per ogni elemento nella tabella di spostamento. Ciò indica che si sta verificando una valutazione eager, che non è ideale quando si creano tabelle di spostamento con molti elementi. Le lezioni successive illustrano come creare una tabella di spostamento appropriata che supporti la valutazione differita.
Conclusione
Questa lezione ha illustrato come creare un connettore semplice per un servizio REST. In questo caso, è stata trasformata un'estensione OData esistente in un'estensione REST standard (usando Web.Contents), ma gli stessi concetti si applicano se si sta creando una nuova estensione da zero.
Nella lezione successiva verranno eseguite le query create in questa lezione usando Power BI Desktop e convertirle in una tabella di spostamento vera all'interno dell'estensione.