TripPin parte 4 - Caminhos da fonte de dados
Este tutorial com 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 incrementalmente novos recursos ao seu conector.
Nesta lição, você irá:
- Simplifique a lógica de conexão para seu conector
- Melhorar a experiência da tabela de navegação
Esta lição simplifica o conector criado na lição anterior, removendo seus parâmetros de função necessários e melhorando a experiência do usuário movendo-se para uma tabela de navegação gerada dinamicamente.
Para obter uma explicação detalhada de como as credenciais são identificadas, consulte a seção Caminhos da fonte de dados de Manipulando autenticação.
Caminhos da fonte de dados
Ao invocar uma função de fonte de dados, o mecanismo M identifica quais credenciais usar durante uma avaliação fazendo uma pesquisa com base nos valores Tipo de Fonte de Dados e Caminho da Fonte de Dados.
Na lição anterior, você compartilhou duas funções de fonte de dados, ambas com um único parâmetro Uri.Type.
[DataSource.Kind="TripPin"]
shared TripPin.Feed = Value.ReplaceType(TripPinImpl, type function (url as Uri.Type) as any);
[DataSource.Kind="TripPin", Publish="TripPin.Publish"]
shared TripPin.Contents = Value.ReplaceType(TripPinNavTable, type function (url as Uri.Type) as any);
Na primeira vez que executar uma consulta que usa uma das funções, você receberá um prompt de credencial com menus suspensos que permite selecionar um caminho e um tipo de autenticação.
Se você executar a mesma consulta novamente, com os mesmos parâmetros, o mecanismo M poderá localizar as credenciais armazenadas em cache e nenhum prompt de credenciais será mostrado. Se você modificar o url
argumento para sua função para que o caminho base não corresponda mais, um novo prompt de credenciais será exibido para o novo caminho.
Você pode ver todas as credenciais armazenadas em cache na tabela Credenciais na janela M Query Output .
Dependendo do tipo de alteração, modificar os parâmetros da sua função provavelmente resultará em um erro de credencial.
Simplificando o conector
Agora você simplificará seu conector removendo os parâmetros para sua função de fonte de dados (TripPin.Contents
). Você também removerá o shared
qualificador do TripPin.Feed
, e o deixará como uma função apenas interna.
Uma das filosofias de design do Power Query é manter o diálogo inicial da fonte de dados o mais simples possível. Se possível, deve fornecer ao utilizador opções ao nível do Navigator, em vez de na caixa de diálogo de ligação. Se um valor fornecido pelo usuário puder ser determinado programaticamente, considere adicioná-lo como o nível superior da tabela de navegação em vez de um parâmetro de função.
Por exemplo, ao se conectar a um banco de dados relacional, você pode precisar de nomes de servidor, banco de dados e tabela.
Depois de saber o servidor ao qual se conectar e as credenciais foram fornecidas, você pode usar a API do banco de dados para buscar uma lista de bancos de dados e uma lista de tabelas contidas em cada banco de dados.
Nesse caso, para manter a caixa de diálogo de conexão inicial o mais simples possível, apenas o nome do servidor deve ser um parâmetro necessário —Database
e Table
seriam os níveis da sua tabela de navegação.
Como o serviço TripPin tem um ponto de extremidade de URL fixo, não é necessário solicitar nenhum valor ao usuário. Você removerá o parâmetro url da sua função e definirá uma variável BaseUrl no seu conector.
BaseUrl = "https://services.odata.org/v4/TripPinService/";
[DataSource.Kind="TripPin", Publish="TripPin.Publish"]
shared TripPin.Contents = () => TripPinNavTable(BaseUrl) as table;
Você manterá a TripPin.Feed
função, mas não a tornará mais compartilhada, não a associará mais a um tipo de fonte de dados e simplificará sua declaração. A partir deste ponto, você só o usará internamente neste documento de seção.
TripPin.Feed = (url as text) =>
let
source = Web.Contents(url, [ Headers = DefaultRequestHeaders ]),
json = Json.Document(source)
in
json;
Se você atualizar a TripPin.Contents()
chamada em seu TripPin.query.pq
arquivo e executá-la no Visual Studio Code, verá um novo prompt de credenciais. Observe que agora há um único valor de Caminho da Fonte de Dados — TripPin.
Melhorar a tabela de navegação
No primeiro tutorial, você usou as funções integradas OData
para se conectar ao serviço TripPin.
Isso lhe deu uma mesa de navegação bonita, baseada no documento de serviço do TripPin, sem mais código do seu lado.
A função OData.Feed automaticamente fez o trabalho duro para você.
Uma vez que você está "aproximando-o" usando Web.Contents em vez de OData.Feed, você precisará recriar esta tabela de navegação por conta própria.
Você fará as seguintes alterações:
- Definir uma lista de itens a mostrar na sua tabela de navegação
- Eliminar as funções específicas da entidade (
GetAirlineTables
eGetAirportsTable
)
Gerar uma tabela de navegação a partir de uma lista
Você listará as entidades que deseja expor na tabela de navegação e criará a URL apropriada para acessá-las. Como todas as entidades estão sob o mesmo caminho raiz, você poderá criar essas URLs dinamicamente.
Para simplificar o exemplo, você exporá apenas os três conjuntos de entidades (Companhias Aéreas, Aeroportos, Pessoas), que seriam expostos como Tabelas em M, e ignorará o singleton (Me) que seria exposto como um Registro. Você pulará a adição das funções até uma lição posterior.
RootEntities = {
"Airlines",
"Airports",
"People"
};
Em seguida, você atualiza sua TripPinNavTable
função para criar a tabela uma coluna de cada vez.
A coluna [Dados] de cada entidade é recuperada chamando TripPin.Feed
com a URL completa para a entidade.
TripPinNavTable = (url as text) as table =>
let
entitiesAsTable = Table.FromList(RootEntities, Splitter.SplitByNothing()),
rename = Table.RenameColumns(entitiesAsTable, {{"Column1", "Name"}}),
// Add Data as a calculated column
withData = Table.AddColumn(rename, "Data", each TripPin.Feed(Uri.Combine(url, [Name])), Uri.Type),
// Add ItemKind and ItemName as fixed text values
withItemKind = Table.AddColumn(withData, "ItemKind", each "Table", type text),
withItemName = Table.AddColumn(withItemKind, "ItemName", each "Table", type text),
// Indicate that the node should not be expandable
withIsLeaf = Table.AddColumn(withItemName, "IsLeaf", each true, type logical),
// Generate the nav table
navTable = Table.ToNavigationTable(withIsLeaf, {"Name"}, "Name", "Data", "ItemKind", "ItemName", "IsLeaf")
in
navTable;
Ao criar caminhos de URL dinamicamente, certifique-se de que está claro onde estão as barras (/)! Observe que Uri.Combine usa as seguintes regras ao combinar caminhos:
- Quando o
relativeUri
parâmetro começa com um /, ele substituirá todo obaseUri
caminho do parâmetro - Se o
relativeUri
parâmetro não começar com um / ebaseUri
terminar com um /, o caminho será acrescentado - Se o
relativeUri
parâmetro não começar com um / ebaseUri
não terminar com um /, o último segmento do caminho será substituído
A imagem a seguir mostra exemplos disso:
Remover as funções específicas da entidade
Para facilitar a manutenção do conector, você removerá as funções de formatação específicas da entidade usadas na lição anterior —GetAirlineTables
e GetAirportsTable
.
Em vez disso, você atualizará TripPin.Feed
para processar a resposta JSON de uma forma que funcione para todas as suas entidades.
Especificamente, você pega o value
campo da carga JSON OData retornada e o converte de uma lista de registros em uma tabela.
TripPin.Feed = (url as text) =>
let
source = Web.Contents(url, [ Headers = DefaultRequestHeaders ]),
json = Json.Document(source),
// The response is a JSON record - the data we want is a list of records in the "value" field
value = json[value],
asTable = Table.FromList(value, Splitter.SplitByNothing()),
// expand all columns from the record
fields = Record.FieldNames(Table.FirstValue(asTable, [Empty = null])),
expandAll = Table.ExpandRecordColumn(asTable, "Column1", fields)
in
expandAll;
Nota
Uma desvantagem de usar uma abordagem genérica para processar suas entidades é que você perde a formatação agradável e as informações de tipo para suas entidades. Uma seção posterior neste tutorial mostra como impor o esquema em chamadas de API REST.
Conclusão
Neste tutorial, você limpou e simplificou o conector corrigindo o valor do Caminho da Fonte de Dados e mudando para um formato mais flexível para a tabela de navegação. Depois de concluir essas etapas (ou usar o código de exemplo neste diretório), a TripPin.Contents
função retorna uma tabela de navegação no Power BI Desktop.