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).
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:
- Importera den gemensamma
Table.GenerateByPage
funktionen - Lägg till en
GetAllPagesByNextLink
funktion som använderTable.GenerateByPage
för att limma ihop alla sidor - Lägga till en
GetPage
funktion som kan läsa en enda sida med data - Lägga till en
GetNextLink
funktion för att extrahera nästa URL från svaret - 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.GenerateByPage
vi . 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.
Implementera GetAllPagesByNextLink
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];
Implementera GetNextLink
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.
Om du tittar på begäranden i Fiddler bör du nu se separata begäranden för varje sida med data.
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
.