Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este tutorial de várias partes aborda a criação de uma nova extensão de fonte de dados para o Power Query. O tutorial deve ser feito sequencialmente — cada lição se baseia no conector criado nas lições anteriores, adicionando progressivamente novos recursos ao conector.
Nesta lição, você:
- Criar uma função base que chama uma API REST usando Web.Contents
- Saiba como definir cabeçalhos de solicitação e processar uma resposta JSON
- Usar o Power BI Desktop para definir a resposta em um formato amigável
Esta lição converte o conector baseado em OData para o serviço TripPin (criado na lição anterior) em um conector semelhante a algo que você criaria para qualquer API RESTful. OData é uma API RESTful, mas uma com um conjunto fixo de convenções. A vantagem do OData é que ele fornece um esquema, um protocolo de recuperação de dados e uma linguagem de consulta padrão. Remover o uso do OData.Feed exige que você crie essas funcionalidades no conector por conta própria.
Resumo do conector OData
Antes de remover as funções OData do 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 arquivo de consulta e cole a seguinte consulta:
TripPin.Feed("https://services.odata.org/v4/TripPinService/Me")
Abra o Fiddler e, em seguida, avalie o arquivo power query atual no Visual Studio Code.
No Fiddler, há três solicitações para o servidor:
-
/Me: a URL real que você está solicitando. -
/$metadata: uma chamada feita automaticamente pela funçãoOData.Feedpara determinar informações esquemáticas e de tipo sobre a resposta. -
/Me/BestFriend: um dos campos que foi (ansiosamente) recuperado quando você listou o objeto singleton /Me. Nesse caso, a chamada resultou em um204 No Contentstatus.
A avaliação M é preguiçosa. Na maioria dos casos, os valores de dados só são recuperados/extraídos quando são necessários. Há cenários (como o caso /Me/BestFriend) em que um valor é puxado ansiosamente. Esse comportamento tende a ocorrer quando as informações de tipo são necessárias para um membro e o motor não possui nenhum outro método para determinar o tipo, além de recuperar o valor e inspecioná-lo. Tornar as operações preguiçosas (ou seja, evitar execuções imediatas) é um dos principais aspectos para tornar um conector M eficiente em termos de desempenho.
Dê uma olhada nos cabeçalhos de solicitação que foram enviados junto com as solicitações e o formato JSON da resposta da solicitação /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 deverá mostrar o valor de Registro para o singleton Me.
Se você comparar os campos na janela de saída com os campos retornados na resposta JSON bruta, você observará uma incompatibilidade. O resultado da consulta tem outros campos (Friends, , TripsGetFriendsTrips) que não aparecem em nenhum lugar na resposta JSON. A função OData.Feed anexa automaticamente esses campos ao registro com base no esquema retornado por $metadata. Essa diferença é um bom exemplo de como um conector pode aumentar e/ou reformatar a resposta do serviço para fornecer uma melhor experiência do usuário.
Criando um conector REST básico
Agora, adicione uma nova função exportada ao conector que chama Web.Contents.
No entanto, para fazer solicitações da Web bem-sucedidas para o serviço OData, você precisa definir alguns cabeçalhos OData padrão. Você faz isso definindo um conjunto comum de cabeçalhos como uma nova variável em seu conector:
DefaultRequestHeaders = [
#"Accept" = "application/json;odata.metadata=minimal", // column name and values only
#"OData-MaxVersion" = "4.0" // we only support v4
];
Você altera a implementação da função TripPin.Feed para que, em vez de usar OData.Feed, ela use Web.Contents para fazer uma solicitação da 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;
Lembre-se de construir seu conector agora que você fez alterações no arquivo do conector. Em seguida, você pode avaliar o arquivo de consulta (TripPin.query.pq). O resultado do registro /Me agora se assemelha ao JSON sem formatação que estava na solicitação Fiddler.
Se você observar o Fiddler ao executar a nova função, também observará que a avaliação agora faz uma única solicitação da Web, em vez de três. Parabéns: você conseguiu um aumento de desempenho de 300%! Agora você perdeu todas as informações de tipo e esquema, mas ainda não há necessidade de se concentrar nessa parte.
Atualize sua consulta para acessar algumas das Entidades/Tabelas TripPin, como:
https://services.odata.org/v4/TripPinService/Airlineshttps://services.odata.org/v4/TripPinService/Airportshttps://services.odata.org/v4/TripPinService/Me/Trips
Observe que os caminhos usados para retornar tabelas bem formatadas agora retornam um campo de "valor" de nível superior com uma [Lista] inserida. Você precisa fazer algumas transformações no resultado para torná-lo utilizável para cenários de consumo do usuário final.
Elaborando transformações no Power Query
Embora seja possível criar suas transformações de M manualmente, a maioria das pessoas prefere usar o Power Query para moldar seus dados. Abra sua extensão no Power BI Desktop e use-a para criar consultas para transformar a saída em um formato mais amigável. Recompile sua solução, copie o novo arquivo de extensão para o diretório Conectores de Dados Personalizados, e relance 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 sinal = .
Manipule a saída até que ela se pareça com o feed OData original— uma tabela com duas colunas: AirlineCode e Name.
A consulta resultante deve ser semelhante a esta:
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 para a consulta ("Airlines").
Crie uma nova consulta em branco. Desta vez, use a TripPin.Feed função para acessar a entidade /Airports. Aplique transformações até obter algo semelhante à tabela a seguir. A consulta correspondente segue a tabela , dê a essa consulta um nome ("Aeroportos") também.
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"
Você pode repetir esse processo para obter mais caminhos no serviço. Quando estiver pronto, vá para a próxima etapa da criação de uma tabela de navegação (simulada).
Simulando uma tabela de navegação
Agora você vai criar uma tabela (usando o código M) que apresenta suas entidades TripPin bem formatadas.
Inicie uma nova consulta em branco e abra o editor avançado.
Cole a seguinte consulta:
let
source = #table({"Name", "Data"}, {
{ "Airlines", Airlines },
{ "Airports", Airports }
})
in
source
Se você não definiu sua configuração de Níveis de Privacidade como "Sempre ignorar configurações de nível de privacidade" (também conhecida como "Combinação Rápida"), um prompt de privacidade será exibido.
Os prompts de privacidade aparecem quando você está combinando dados de várias fontes e não especifica um nível de privacidade para uma ou mais fontes. Selecione o botão Continuar e defina o nível de privacidade da fonte superior como Público.
Selecione Salvar e sua tabela será exibida. Embora esta tabela ainda não seja uma tabela de navegação, ela fornece a funcionalidade básica necessária para transformá-la em uma em uma lição subsequente.
As verificações de combinação de dados não ocorrem ao acessar várias fontes de dados de dentro de uma extensão. Como todas as chamadas de fonte de dados feitas de dentro da extensão herdam o mesmo contexto de autorização, a suposição é que elas são "seguras" para combinar. Sua extensão sempre é tratada como uma única fonte de dados quando se trata de regras de combinação de dados. Os usuários ainda receberiam os prompts de privacidade regulares ao combinar sua origem com outras fontes M.
Se você executar o Fiddler e selecionar o botão Atualizar Visualização no editor do Power Query, observe as solicitações da Web separadas para cada item na tabela de navegação. Essas solicitações separadas indicam que uma avaliação ansiosa está ocorrendo, o que não é ideal ao criar tabelas de navegação com muitos elementos. As lições subsequentes mostram como criar uma tabela de navegação adequada que dá suporte à avaliação lenta.
Conclusion
Esta lição mostrou como criar um conector simples para um serviço REST. Nesse caso, você transformou uma extensão OData existente em uma extensão REST padrão (usando Web.Contents), mas os mesmos conceitos se aplicam se você estiver criando uma nova extensão do zero.
Na próxima lição, você pega as consultas criadas nesta lição usando o Power BI Desktop e as transforma em uma verdadeira tabela de navegação dentro da extensão.