Dela via


TripPin del 4 – Sökvägar för datakälla

Den här självstudien i flera delar beskriver hur du skapar ett nytt datakällans tillägg för Power Query. Självstudien är avsedd att utföras sekventiellt – varje lektion bygger på anslutningsappen som skapades i föregående lektioner och lägger stegvis till nya funktioner i anslutningsappen.

I den här lektionen kommer du att:

  • Förenkla anslutningslogik för anslutningsappen
  • Förbättra navigeringstabellens upplevelse

Den här lektionen förenklar anslutningsappen som skapades i föregående lektion genom att ta bort dess nödvändiga funktionsparametrar och förbättra användarupplevelsen genom att flytta till en dynamiskt genererad navigeringstabell.

En detaljerad förklaring av hur autentiseringsuppgifter identifieras finns i avsnittet Sökvägar för datakällor i Hantering av autentisering.

Sökvägar för datakälla

När du anropar en datakällsfunktion identifierar M-motorn vilka autentiseringsuppgifter som ska användas under en utvärdering genom att göra en sökning baserat på värdena datakälltyp och datakällsökväg .

I föregående lektion delade du två datakällans funktioner, båda med en enda Uri.Type-parameter .

[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);

Första gången du kör en fråga som använder en av funktionerna får du en fråga om autentiseringsuppgifter med listrutor där du kan välja en sökväg och en autentiseringstyp.

Autentiseringsuppgifter med sökvägar.

Om du kör samma fråga igen, med samma parametrar, kan M-motorn hitta de cachelagrade autentiseringsuppgifterna och ingen fråga om autentiseringsuppgifter visas. Om du ändrar url argumentet till din funktion så att bassökvägen inte längre matchar visas en ny fråga om autentiseringsuppgifter för den nya sökvägen.

Du kan se cachelagrade autentiseringsuppgifter i tabellen Autentiseringsuppgifter i fönstret M Query-utdata .

Fliken Autentiseringsuppgifter.

Beroende på typen av ändring resulterar det sannolikt i ett autentiseringsfel om du ändrar parametrarna för funktionen.

Förenkla anslutningsappen

Nu ska du förenkla anslutningsappen genom att ta bort parametrarna för datakällfunktionen (TripPin.Contents). Du tar också bort kvalificeraren shared för TripPin.Feedoch lämnar den som en intern funktion.

En av designfilosofierna i Power Query är att hålla den inledande datakällans dialogruta så enkel som möjligt. Om det är möjligt bör du ge användaren val på navigatörsnivå i stället för i anslutningsdialogrutan. Om ett användarvärde kan fastställas programmatiskt kan du överväga att lägga till det som den översta nivån i navigeringstabellen i stället för en funktionsparameter.

När du till exempel ansluter till en relationsdatabas kan du behöva server-, databas- och tabellnamn. När du vet att servern ska ansluta till och autentiseringsuppgifter har angetts kan du använda databasens API för att hämta en lista över databaser och en lista över tabeller som finns i varje databas. I det här fallet bör endast servernamnet vara en obligatorisk parameter för att hålla den inledande anslutningsdialogrutan så enkel som möjligt,Database och Table den skulle vara nivåer i navigeringstabellen.

Eftersom TripPin-tjänsten har en fast URL-slutpunkt behöver du inte fråga användaren om några värden. Du tar bort url-parametern från funktionen och definierar en BaseUrl-variabel i anslutningsappen.

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

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

Du behåller funktionen, men inte längre delar den TripPin.Feed , associerar den inte längre med en typ av datakälla och förenklar deklarationen. Från och med nu använder du den endast internt i det här avsnittsdokumentet.

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

Om du uppdaterar anropet TripPin.Contents() i TripPin.query.pq filen och kör det i Visual Studio Code visas en ny fråga om autentiseringsuppgifter. Observera att det nu finns ett enda värde för sökvägen till datakällan – TripPin.

Autentiseringsuppgifter utan sökväg.

Förbättra navigeringstabellen

I den första självstudien använde du de inbyggda OData funktionerna för att ansluta till TripPin-tjänsten. Detta gav dig en snygg navigeringstabell, baserad på TripPin-tjänstdokumentet, utan mer kod på din sida. Funktionen OData.Feed gjorde automatiskt det hårda arbetet åt dig. Eftersom du använder web.content i stället för OData.Feed måste du återskapa den här navigeringstabellen själv.

OData Navigator.

Du kommer att göra följande ändringar:

  1. Definiera en lista över objekt som ska visas i navigeringstabellen
  2. Ta bort de entitetsspecifika funktionerna (GetAirlineTables och GetAirportsTable)

Generera en navigeringstabell från en lista

Du visar en lista över de entiteter som du vill exponera i navigeringstabellen och skapar lämplig URL för att komma åt dem. Eftersom alla entiteter är under samma rotsökväg kan du skapa dessa URL:er dynamiskt.

För att förenkla exemplet exponerar du bara de tre entitetsuppsättningarna (Airlines, Airports, People), som skulle exponeras som tabeller i M, och hoppa över den singleton (Mig) som skulle exponeras som en post. Du hoppar över att lägga till funktionerna till en senare lektion.

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

Sedan uppdaterar du funktionen TripPinNavTable för att skapa tabellen en kolumn i taget. Kolumnen [Data] för varje entitet hämtas genom att anropa TripPin.Feed med den fullständiga URL:en till entiteten.

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;

När du dynamiskt skapar URL-sökvägar ser du till att du är tydlig med var dina snedstreck (/) finns! Observera att Uri.Combine använder följande regler när du kombinerar sökvägar:

  • När parametern relativeUri börjar med en /ersätter den hela sökvägen för parametern baseUri
  • Om parametern relativeUri inte börjar med /och baseUri slutar med /, läggs sökvägen till
  • Om parametern relativeUri inte börjar med /och baseUri inte slutar med /, ersätts sökvägens sista segment

Följande bild visar exempel på detta:

Uri.Combine-exempel.

Ta bort entitetsspecifika funktioner

För att göra anslutningsappen enklare att underhålla tar du bort de entitetsspecifika formateringsfunktioner som du använde i föregående lektion–GetAirlineTables och GetAirportsTable. I stället uppdaterar TripPin.Feed du för att bearbeta JSON-svaret på ett sätt som fungerar för alla dina entiteter. Mer specifikt tar value du fältet för den returnerade OData JSON-nyttolasten och konverterar den från en lista med poster till en tabell.

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;

Kommentar

En nackdel med att använda en allmän metod för att bearbeta dina entiteter är att du förlorar den fina formateringen och skriver information för dina entiteter. Ett senare avsnitt i den här självstudien visar hur du framtvingar schema för REST API-anrop.

Slutsats

I den här självstudien har du rensat och förenklat anslutningsappen genom att åtgärda värdet för datakällans sökväg och flytta till ett mer flexibelt format för navigeringstabellen. När du har slutfört de här stegen (eller använt exempelkoden i den TripPin.Contents här katalogen) returnerar funktionen en navigeringstabell i Power BI Desktop.

Navigatör.

Nästa steg

TripPin, del 5 – sidindelning