Dela via


TripPin del 5 - Sidindelning

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:

  • Lägga till stöd för växling i anslutningsappen

Många rest-API:er returnerar data i "sidor", vilket kräver att klienter gör flera begäranden för att sammanfoga resultaten. Även om det finns några vanliga konventioner för sidnumrering (till exempel RFC 5988), varierar det vanligtvis från API till API. Som tur är är TripPin en OData-tjänst och OData-standarden definierar ett sätt att göra sidnumrering med hjälp av odata.nextLink-värden som returneras i brödtexten i svaret.

För att förenkla tidigare iterationer av anslutningsappen TripPin.Feed var funktionen inte sidmedveten. Den parsade helt enkelt det JSON som returnerades från begäran och formaterade den som en tabell. De som är bekanta med OData-protokollet kanske har märkt att många felaktiga antaganden gjordes i formatet för svaret (till exempel om det finns ett value fält som innehåller en matris med poster).

I den här lektionen får du bättre svarshanteringslogik genom att göra sidan medveten. Framtida självstudier gör sidhanteringslogik mer robust och kan hantera flera svarsformat (inklusive fel från tjänsten).

Kommentar

Du behöver inte implementera din egen växlingslogik med anslutningsappar baserade på OData.Feed, eftersom den hanterar allt åt dig automatiskt.

Checklista för växling

När du implementerar växlingsstöd behöver du veta följande om ditt API:

  • Hur begär du nästa sida med data?
  • Omfattar växlingsmekanismen beräkning av värden, eller extraherar du URL:en för nästa sida från svaret?
  • Hur vet du när du ska sluta söka?
  • Finns det parametrar som rör växling som du bör känna till? (till exempel "sidstorlek")

Svaret på dessa frågor påverkar hur du implementerar växlingslogik. Det finns en viss mängd återanvändning av kod i växlingsimplementeringar (till exempel användning av Table.GenerateByPage, men de flesta anslutningsappar kräver anpassad logik.

Kommentar

Den här lektionen innehåller växlingslogik för en OData-tjänst som följer ett visst format. Kontrollera dokumentationen för ditt API för att fastställa vilka ändringar du behöver göra i anslutningsappen för att stödja växlingsformatet.

Översikt över OData-växling

OData-växling drivs av nextLink-anteckningar som finns i svarsnyttolasten. Värdet nextLink innehåller URL:en till nästa sida med data. Du vet om det finns en annan sida med data genom att leta efter ett odata.nextLink fält i det yttersta objektet i svaret. Om det inte finns något odata.nextLink fält har du läst alla dina data.

{
  "odata.context": "...",
  "odata.count": 37,
  "value": [
    { },
    { },
    { }
  ],
  "odata.nextLink": "...?$skiptoken=342r89"
}

Vissa OData-tjänster gör det möjligt för klienter att ange en inställning för maximal sidstorlek, men det är upp till tjänsten om den ska respekteras eller inte. Power Query bör kunna hantera svar av valfri storlek, så du behöver inte bekymra dig om att ange en inställning för sidstorlek – du kan stödja det som tjänsten kastar på dig.

Mer information om serverdriven växling finns i OData-specifikationen.

Testa TripPin

Innan du åtgärdar växlingsimplementeringen bekräftar du det aktuella beteendet för tillägget från föregående självstudie. Följande testfråga hämtar tabellen Personer och lägger till en indexkolumn för att visa ditt aktuella radantal.

let
    source = TripPin.Contents(),
    data = source{[Name="People"]}[Data],
    withRowCount = Table.AddIndexColumn(data, "Index")
in
    withRowCount

Aktivera Fiddler och kör frågan i Power Query SDK. Observera att frågan returnerar en tabell med åtta rader (index 0 till 7).

QueryWithoutPaging.

Om du tittar på brödtexten i svaret från fiddler ser du att det faktiskt innehåller ett @odata.nextLink fält, vilket indikerar att det finns fler tillgängliga sidor med data.

{
  "@odata.context": "https://services.odata.org/V4/TripPinService/$metadata#People",
  "@odata.nextLink": "https://services.odata.org/v4/TripPinService/People?%24skiptoken=8",
  "value": [
    { },
    { },
    { }
  ]
}

Implementera växling för TripPin

Nu ska du göra följande ändringar i tillägget:

  1. Importera den gemensamma Table.GenerateByPage funktionen
  2. Lägg till en GetAllPagesByNextLink funktion som använder Table.GenerateByPage för att limma ihop alla sidor
  3. Lägga till en GetPage funktion som kan läsa en enda sida med data
  4. Lägga till en GetNextLink funktion för att extrahera nästa URL från svaret
  5. Uppdatera TripPin.Feed för att använda de nya sidläsarfunktionerna

Kommentar

Som tidigare nämnts i den här självstudien varierar växlingslogik mellan datakällor. Implementeringen här försöker dela upp logiken i funktioner som ska kunna återanvändas för källor som använder nästa länkar som returneras i svaret.

Table.GenerateByPage

Om du vill kombinera (potentiellt) flera sidor som returneras av källan till en enda tabell använder Table.GenerateByPagevi . Den här funktionen tar som argument en getNextPage funktion som ska göra precis vad namnet antyder: hämta nästa sida med data. Table.GenerateByPage anropar getNextPage funktionen upprepade gånger, varje gång resultatet som producerades senast anropades, tills den återgår null för att signalera tillbaka att inga fler sidor är tillgängliga.

Eftersom den här funktionen inte ingår i Power Querys standardbibliotek måste du kopiera källkoden till .pq-filen.

Funktionens GetAllPagesByNextLink brödtext implementerar funktionsargumentet getNextPage för Table.GenerateByPage. Den anropar GetPage funktionen och hämtar URL:en för nästa sida med data från NextLink fältet i meta posten från föregående anrop.

// Read all pages of data.
// After every page, we check the "NextLink" record on the metadata of the previous request.
// Table.GenerateByPage will keep asking for more pages until we return null.
GetAllPagesByNextLink = (url as text) as table =>
    Table.GenerateByPage((previous) => 
        let
            // if previous is null, then this is our first page of data
            nextLink = if (previous = null) then url else Value.Metadata(previous)[NextLink]?,
            // if NextLink was set to null by the previous call, we know we have no more data
            page = if (nextLink <> null) then GetPage(nextLink) else null
        in
            page
    );

Implementera GetPage

Funktionen GetPage använder Web.Contents för att hämta en enda sida med data från TripPin-tjänsten och konvertera svaret till en tabell. Det skickar svaret från Web.Contents till GetNextLink funktionen för att extrahera URL:en för nästa sida och anger den i meta posten för den returnerade tabellen (datasida).

Den här implementeringen är en något modifierad version av anropet TripPin.Feed från de tidigare självstudierna.

GetPage = (url as text) as table =>
    let
        response = Web.Contents(url, [ Headers = DefaultRequestHeaders ]),        
        body = Json.Document(response),
        nextLink = GetNextLink(body),
        data = Table.FromRecords(body[value])
    in
        data meta [NextLink = nextLink];

Funktionen GetNextLink kontrollerar helt enkelt svarets brödtext för ett @odata.nextLink fält och returnerar dess värde.

// In this implementation, 'response' will be the parsed body of the response after the call to Json.Document.
// Look for the '@odata.nextLink' field and simply return null if it doesn't exist.
GetNextLink = (response) as nullable text => Record.FieldOrDefault(response, "@odata.nextLink");

Färdigställa allt

Det sista steget för att implementera växlingslogik är att uppdatera TripPin.Feed för att använda de nya funktionerna. För tillfället anropar du bara till GetAllPagesByNextLink, men i efterföljande självstudier kommer du att lägga till nya funktioner (till exempel att framtvinga ett schema och frågeparameterlogik).

TripPin.Feed = (url as text) as table => GetAllPagesByNextLink(url);

Om du kör samma testfråga igen från tidigare i självstudien bör du nu se sidläsaren i praktiken. Du bör också se att du har 24 rader i svaret i stället för åtta.

QueryWithPaging.

Om du tittar på begäranden i Fiddler bör du nu se separata begäranden för varje sida med data.

Spelman.

Kommentar

Du ser dubbletter av begäranden för den första sidan med data från tjänsten, vilket inte är idealiskt. Den extra begäran är ett resultat av M-motorns schemakontrollbeteende. Ignorera det här problemet för tillfället och lös det i nästa självstudie, där du använder ett explicit schema.

Slutsats

Den här lektionen visade hur du implementerar sidnumreringsstöd för ett rest-API. Även om logiken sannolikt varierar mellan API:er bör mönstret som anges här återanvändas med mindre ändringar.

I nästa lektion tittar du på hur du använder ett explicit schema för dina data, utöver de enkla text datatyper och number datatyper som du får från Json.Document.

Nästa steg

TripPin Del 6 – Schema