Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Este tutorial em várias partes aborda a criação de uma nova extensão de fonte de dados para o Power Query. O tutorial destina-se a ser feito sequencialmente — cada lição baseia-se no conector criado nas aulas anteriores, adicionando gradualmente novas capacidades ao seu conector.
Nesta lição, vocês:
- Crie uma função base que chame para uma API REST usando Web.Contents
- Aprenda a definir cabeçalhos de pedidos e processar uma resposta JSON
- Use o Power BI Desktop para organizar a resposta num formato amigável para o utilizador
Esta lição converte o conector baseado em OData para o serviço TripPin (criado na lição anterior) num conector que se assemelha a algo que criaria para qualquer API RESTful. O OData é uma API RESTful, mas com um conjunto fixo de convenções. A vantagem do OData é que fornece um esquema, protocolo de recuperação de dados e linguagem de consulta padrão. Retirar o uso do OData.Feed exige que incorpore estas capacidades no conector por você mesmo.
Recapitulação do conector OData
Antes de remover as funções OData do seu conector, vamos fazer uma revisão rápida do que ele faz atualmente (principalmente nos bastidores) para recuperar dados do serviço.
Abra o projeto de extensão TripPin da Parte 1 no Visual Studio Code. Abra o ficheiro de consulta e cole a seguinte consulta:
TripPin.Feed("https://services.odata.org/v4/TripPinService/Me")
Abra o Fiddler e depois avalie o ficheiro Power Query atual no Visual Studio Code.
No Fiddler, existem três pedidos para o servidor:
-
/Me: O URL real que estás a pedir. -
/$metadata: Uma chamada feita automaticamente pela funçãoOData.Feedpara determinar as informações sobre o esquema e o tipo da resposta. -
/Me/BestFriend: Um dos campos que foi extraído com entusiasmo ao listares o singleton /Me. Neste caso, a chamada resultou num204 No Contentestado.
A avaliação do M é, na maior parte, preguiçosa. Na maioria dos casos, os valores dos dados só são recuperados/retirados quando são necessários. Existem cenários (como o caso /Me/BestFriend) em que um valor é retirado com entusiasmo. Este comportamento tende a ocorrer quando a informação do tipo é necessária para um membro, e o motor não tem outra forma de determinar o tipo senão recuperar o valor e inspecioná-lo. Tornar as coisas preguiçosas (ou seja, evitar puxagens excessivas) é um dos aspetos-chave para tornar um conector M eficiente.
Veja os cabeçalhos dos pedidos que foram enviados juntamente com os pedidos e o formato JSON da resposta ao pedido /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
}
Quando a consulta terminar de ser avaliada, a janela de resultados do PQTest deve mostrar o valor de Registo para o singleton Me.
Se comparar os campos na janela de saída com os campos devolvidos na resposta JSON bruta, nota uma incompatibilidade. O resultado da consulta tem outros campos (Friends, Trips, GetFriendsTrips) que não aparecem em lado nenhum na resposta JSON. A função OData.Feed adicionava automaticamente estes campos ao registo com base no esquema devolvido por $metadata. Esta diferença é um bom exemplo de como um conector pode aumentar e/ou reformatar a resposta do serviço para proporcionar uma melhor experiência ao utilizador.
Criação de um conector REST básico
Agora adicione uma nova função exportada ao seu conector que chame Web.Contents.
Para fazer pedidos web bem-sucedidos ao serviço OData, no entanto, é necessário definir alguns cabeçalhos OData padrão. Fazes isto definindo um conjunto comum de cabeçalhos como uma nova variável no teu conector:
DefaultRequestHeaders = [
#"Accept" = "application/json;odata.metadata=minimal", // column name and values only
#"OData-MaxVersion" = "4.0" // we only support v4
];
Muda a implementação da sua TripPin.Feed função para que, em vez de usar OData.Feed, use Web.Contents para fazer um pedido web e analise o resultado como um documento JSON.
TripPinImpl = (url as text) =>
let
source = Web.Contents(url, [ Headers = DefaultRequestHeaders ]),
json = Json.Document(source)
in
json;
Lembra-te de construir o teu conector agora que fizeste alterações ao ficheiro do conector. Depois podes avaliar o ficheiro de consulta (TripPin.query.pq). O resultado do registo /Me assemelha-se agora ao JSON bruto que estava no pedido do Fiddler.
Se observares o Fiddler enquanto executas a nova função, também reparas que a avaliação agora faz um único pedido web, em vez de três. Parabéns — conseguiu um aumento de desempenho de 300%! Agora perdeste toda a informação de tipo e esquema, mas não há necessidade de te focares nessa parte ainda.
Atualize a sua consulta para aceder a algumas das Entidades/Tabelas TripPin, tais como:
https://services.odata.org/v4/TripPinService/Airlineshttps://services.odata.org/v4/TripPinService/Airportshttps://services.odata.org/v4/TripPinService/Me/Trips
Repara que os caminhos que antes devolviam tabelas bem formatadas agora devolvem um campo "valor" de topo com uma [Lista] incorporada. É necessário fazer algumas transformações no resultado para o tornar utilizável em cenários de consumo do utilizador final.
Criação de transformações no Power Query
Embora seja possível criar as suas transformações M manualmente, a maioria das pessoas prefere usar o Power Query para moldar os seus dados. Abres a tua extensão no Power BI Desktop e usas-na para desenhar consultas que transformem o resultado num formato mais amigável. Reconstrua a sua solução, copie o novo ficheiro de extensão para o diretório Custom Data Connectors e reinicie o Power BI Desktop.
Inicie uma nova Consulta em Branco e cole a seguinte linha na barra de fórmulas:
= TripPin.Feed("https://services.odata.org/v4/TripPinService/Airlines")
Certifique-se de incluir o símbolo =.
Manipule a saída até parecer o feed original OData—uma tabela com duas colunas: AirlineCode e Name.
A consulta resultante deverá ser algo assim:
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
Dê um nome à consulta ("Companhias Aéreas").
Crie uma nova Consulta em Branco. Desta vez, use a TripPin.Feed função para aceder à entidade /Airports. Aplica transformações até obteres algo semelhante à tabela seguinte. A consulta correspondente segue a tabela — dê também um nome a esta consulta ("Aeroportos").
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"
Pode repetir este processo para obter mais caminhos no serviço. Quando estiveres pronto, passa para o passo seguinte de criar uma tabela de navegação (simulada).
Simulação de uma tabela de navegação
Agora vais construir uma tabela (usando código M) que apresenta as tuas entidades TripPin bem formatadas.
Iniciar uma nova Consulta em Branco e abrir o editor avançado.
Cole a seguinte consulta:
let
source = #table({"Name", "Data"}, {
{ "Airlines", Airlines },
{ "Airports", Airports }
})
in
source
Se não definiu a sua definição de Níveis de Privacidade para "Ignorar sempre as definições de Nível de Privacidade" (também conhecida como "Fast Combine"), é exibido um aviso de privacidade.
Os pedidos de privacidade aparecem quando combinas dados de várias fontes e não especificaste um nível de privacidade para uma ou mais fontes. Selecione o botão Continuar e defina o nível de privacidade da fonte principal para Público.
Seleciona Guardar e a tua tabela aparece. Embora esta tabela ainda não seja uma tabela de navegação, fornece a funcionalidade básica necessária para a transformar numa aula seguinte.
Verificações de combinação de dados não ocorrem ao aceder a múltiplas fontes de dados a partir de uma extensão. Como todas as chamadas de fonte de dados feitas dentro da extensão herdam o mesmo contexto de autorização, assume-se que são "seguras" para combinar. A sua extensão é sempre tratada como uma única fonte de dados quando se trata de regras de combinação de dados. Os utilizadores continuariam a receber os pedidos de privacidade normais ao combinar a sua fonte com outras fontes M.
Se executares o Fiddler e selecionares o botão Atualizar Pré-visualização no editor Power Query, anota os pedidos web separados para cada item na tua tabela de navegação. Estas solicitações individuais indicam que está a ocorrer uma avaliação apressada, o que não é ideal ao criar tabelas de navegação com muitos elementos. As lições subsequentes mostram como construir uma tabela de navegação adequada que suporte a avaliação preguiçosa.
Conclusion
Esta lição mostrou-lhe como construir um conector simples para um serviço REST. Neste caso, transformaste uma extensão OData existente numa extensão REST padrão (usando Web.Contents), mas os mesmos conceitos aplicam-se se estiveres a criar uma nova extensão do zero.
Na próxima lição, pega nas consultas criadas nesta lição usando o Power BI Desktop e transforma-as numa verdadeira tabela de navegação dentro da extensão.