Partilhar via


TripPin parte 4 - Caminhos das fontes de dados

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:

  • Simplifica a lógica de ligação para o teu conector
  • Melhorar a experiência da tabela de navegação

Esta lição simplifica o conector incorporado na lição anterior ao remover os parâmetros de função exigidos e melhorar a experiência do utilizador ao passar para uma tabela de navegação gerada dinamicamente.

Para uma explicação aprofundada de como as credenciais são identificadas, consulte a secção de Caminhos de Fonte de Dados de Gestão da Autenticação.

Caminhos da fonte de dados

Quando invoca uma função de fonte de dados, o motor M identifica quais as credenciais a usar durante uma avaliação através de uma pesquisa baseada nos valores do Tipo da Fonte de Dados e do Caminho da Fonte de Dados .

Na lição anterior partilhaste 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 utilizando uma das funções, receberá um prompt de credencial com opções. Este prompt permite-lhe selecionar um caminho e um tipo de autenticação.

Captura de ecrã do separador Erros da saída da consulta M que mostra a mensagem de credenciais.

Se executares novamente a mesma consulta, com os mesmos parâmetros, o motor M consegue localizar as credenciais em cache e não aparece qualquer indicação de credenciais. Se modificar o argumento url da sua função de forma que o caminho base deixe de corresponder, é exibido um novo prompt de credencial para o novo caminho.

Quaisquer credenciais em cache são exibidas na tabela de Credenciais na janela de Saída de Consulta M .

Captura de ecrã da saída da consulta M mostrando as credenciais em cache no separador de credenciais.

Dependendo do tipo de alteração, modificar os parâmetros da sua função provavelmente resulta num erro de credencial.

Simplificar o conector

Agora simplifique o seu conector removendo os parâmetros para a função da fonte de dados (TripPin.Contents). Também tens de remover o shared qualificador para TripPin.Feed, e deixá-lo 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 escolhas ao nível do Navegador, em vez do diálogo de ligação. Se um valor fornecido pelo utilizador puder ser determinado programaticamente, considere adicioná-lo como o nível superior da sua tabela de navegação em vez de um parâmetro de função.

Por exemplo, ao ligar-se a uma base de dados relacional, pode ser necessário nomes de servidor, base de dados e tabelas. Depois de saber a que servidor se deve ligar e de fornecer credenciais, pode usar a API da base de dados para obter uma lista de bases de dados e uma lista de tabelas contidas em cada base de dados. Neste caso, para manter o diálogo inicial de ligação o mais simples possível, apenas o nome do servidor deve ser um parâmetro obrigatório —Database e Table seriam os níveis da sua tabela de navegação.

Como o serviço TripPin tem um endpoint URL fixo, não precisa de pedir valor ao utilizador. Precisas de remover o parâmetro url da tua função e definir uma variável BaseUrl no teu conector.

BaseUrl = "https://services.odata.org/v4/TripPinService/";

[DataSource.Kind="TripPin", Publish="TripPin.Publish"]
shared TripPin.Contents = () => TripPinNavTable(BaseUrl) as table;

Manténs a TripPin.Feed função, mas deixas de a partilhar, não a associas a um Data Source Kind e simplificas a sua declaração. A partir deste ponto, só o usa internamente dentro desta secção do documento.

TripPin.Feed = (url as text) =>
    let
        source = Web.Contents(url, [ Headers = DefaultRequestHeaders ]),
        json = Json.Document(source)
    in
        json;

Se atualizares a TripPin.Contents() invocação no teu ficheiro TripPin.query.pq e a executares no Visual Studio Code, é apresentado um novo pedido de credenciais. Além disso, agora existe um único valor do caminho da fonte de dados — TripPin.

Captura de ecrã do separador Erros da saída da consulta M mostrando a mensagem de credencial que apenas faz referência ao caminho TripPin.

Melhoria da tabela de navegação

No primeiro tutorial, usaste as funções integradas OData para te ligares ao serviço TripPin. Estas funções proporcionaram-lhe uma tabela de navegação de aspeto agradável, baseada no documento de serviço TripPin, sem necessidade de código adicional da sua parte. A função OData.Feed fazia automaticamente o trabalho difícil por si. Como estás a "improvisar" ao usar Web.Contents em vez de OData.Feed, precisas de recriar esta tabela de navegação você mesmo.

Captura de ecrã do Power Query Navigator apresentada ao usar as funções OData integradas.

Vai fazer as seguintes alterações:

  1. Defina uma lista de itens a mostrar na sua tabela de navegação
  2. Eliminar as funções específicas da entidade (GetAirlineTables e GetAirportsTable)

Gerar uma tabela de navegação a partir de uma lista

Precisa de listar as entidades que quer expor na tabela de navegação e construir o URL apropriado para aceder a elas. Como todas as entidades estão sob o mesmo caminho raiz, pode construir estes URLs dinamicamente.

Para simplificar o exemplo, expões apenas os três conjuntos de entidades (Companhias Aéreas, Aeroportos, Pessoas), que seriam expostos como Tabelas em M, e ignoras o singleton (Eu) que seria exposto como Registo. Podes saltar a adição das funções até uma lição posterior.

RootEntities = {
    "Airlines",
    "Airports",
    "People"
};

Depois atualiza a função TripPinNavTable para construir a tabela uma coluna de cada vez. A coluna [Data] para cada entidade é recuperada ao chamar 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 construir caminhos de URL dinamicamente, certifique-se de que está claro onde estão as barras para a frente (/)! O Uri.Combine utiliza as seguintes regras ao combinar caminhos:

  • Quando o relativeUri parâmetro começa com um /, ele substitui todo o caminho do baseUri parâmetro
  • Se o relativeUri parâmetro não começar com / e baseUri em /, o caminho é acrescentado
  • Se o relativeUri parâmetro não começar por / e baseUrinão terminar por /, o último segmento do caminho é substituído

A imagem seguinte mostra exemplos destas regras:

Captura de ecrã dos caminhos URL a mostrar as regras para barras para frente ao combinar caminhos.

Remover as funções específicas da entidade

Para tornar o seu conector mais fácil de manter, precisa de remover as funções de formatação específicas da entidade que usou na lição anterior—GetAirlineTables e GetAirportsTable. Em vez disso, atualiza TripPin.Feed para processar a resposta JSON de uma forma que funcione para todas as suas entidades. Especificamente, pega no campo value da carga útil JSON OData retornada e converte-o de uma lista de registros para 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;

Observação

Uma desvantagem de usar uma abordagem genérica para processar as suas entidades é que se perde a formatação e a informação de tipo adequadas para as suas entidades. Uma secção posterior deste tutorial mostra como aplicar o esquema nas chamadas de API REST.

Conclusion

Neste tutorial, limpaste e simplificaste o teu conector corrigindo o valor do Caminho da Fonte de Dados e passando para um formato mais flexível para a tua tabela de navegação. Depois de completar estes passos (ou usar o código de exemplo neste diretório), a TripPin.Contents função devolve uma tabela de navegação no Power BI Desktop.

Captura de ecrã da tabela de navegação devolvida pela função TripPin.Contents.

Próximos passos

TripPin Parte 5 - Paginação