Del via


TripPin del 5 - Sideveksling

Denne flerdelte opplæringen dekker opprettelsen av en ny datakildeutvidelse for Power Query. Opplæringen er ment å gjøres sekvensielt – hver leksjon bygger på koblingen som er opprettet i tidligere leksjoner, og legger trinnvis til nye funksjoner i koblingen.

I denne leksjonen vil du:

  • Legge til sidevekslingsstøtte i koblingen

Mange rest-API-er returnerer data i «sider», noe som krever at klienter foretar flere forespørsler om å sy sammen resultatene. Selv om det finnes noen vanlige konvensjoner for paginering (for eksempel RFC 5988), varierer det vanligvis fra API til API. Heldigvis er TripPin en OData-tjeneste, og OData-standarden definerer en måte å gjøre paginering på ved hjelp av odata.nextLink-verdier som returneres i brødteksten i svaret.

For å forenkle tidligere gjentakelser av koblingen, TripPin.Feed var ikke funksjonen sidebevisst. Det analyserte ganske enkelt hva JSON ble returnert fra forespørselen og formaterte den som en tabell. De som er kjent med OData-protokollen, har kanskje lagt merke til at mange feilaktige antakelser ble gjort på formatet til svaret (for eksempel forutsatt at det finnes et value felt som inneholder en matrise med poster).

I denne leksjonen kan du forbedre responshåndteringslogikken ved å gjøre den oppmerksom på siden. Fremtidige opplæringer gjør sidehåndteringslogikken mer robust og i stand til å håndtere flere svarformater (inkludert feil fra tjenesten).

Merk

Du trenger ikke å implementere din egen sidevekslingslogikk med koblinger basert på OData.Feed, da den håndterer alt for deg automatisk.

Sjekkliste for sideveksling

Når du implementerer sidevekslingsstøtte, må du vite følgende om API-en:

  • Hvordan ber du om neste side med data?
  • Innebærer sidevekslingsmekanismen å beregne verdier, eller trekker du ut nettadressen for neste side fra svaret?
  • Hvordan vet du når du skal stoppe sideveksling?
  • Er det parametere relatert til sideveksling som du bør være klar over? (for eksempel «sidestørrelse»)

Svaret på disse spørsmålene påvirker måten du implementerer sidevekslingslogikken på. Mens det er en viss mengde kodebruk på tvers av sidevekslingsimplementeringer (for eksempel bruk av Table.GenerateByPage, vil de fleste koblinger ende opp med å kreve egendefinert logikk.

Merk

Denne leksjonen inneholder sidevekslingslogikk for en OData-tjeneste, som følger et bestemt format. Se dokumentasjonen for API-en for å finne ut hvilke endringer du må gjøre i koblingen for å støtte sidevekslingsformatet.

Oversikt over OData-sideveksling

OData-sideveksling drives av nextLink-merknader i nyttelasten for svar. NextLink-verdien inneholder nettadressen til neste side med data. Du vet om det finnes en annen side med data ved å se etter et odata.nextLink felt i det ytterste objektet i svaret. Hvis det ikke er noe odata.nextLink felt, har du lest alle dataene.

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

Noen OData-tjenester gjør det mulig for klienter å angi en maksimal sidestørrelsesinnstillinger, men det er opp til tjenesten om de skal overholde den eller ikke. Power Query skal kunne håndtere svar av alle størrelser, så du trenger ikke å bekymre deg for å angi en innstillinger for sidestørrelse – du kan støtte det tjenesten kaster mot deg.

Du finner mer informasjon om serverdrevet sideveksling i OData-spesifikasjonen.

Testing TripPin

Før du reparerer sidevekslingsimplementeringen, må du bekrefte den gjeldende virkemåten for utvidelsen fra den forrige opplæringen. Følgende testspørring henter Folk-tabellen og legger til en indekskolonne for å vise gjeldende radantall.

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

Slå på Fiddler, og kjør spørringen i Power Query SDK. Vær oppmerksom på at spørringen returnerer en tabell med åtte rader (indeks 0 til 7).

QueryWithoutPaging.

Hvis du ser på brødteksten i svaret fra fiddler, vil du se at det faktisk inneholder et @odata.nextLink felt, noe som indikerer at det er flere sider med data tilgjengelig.

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

Implementere sideveksling for TripPin

Du skal nå gjøre følgende endringer i utvidelsen:

  1. Importer den vanlige Table.GenerateByPage funksjonen
  2. Legge til en GetAllPagesByNextLink funksjon som bruker Table.GenerateByPage til å lime alle sidene sammen
  3. Legge til en GetPage funksjon som kan lese én enkelt side med data
  4. Legg til en GetNextLink funksjon for å trekke ut den neste URL-adressen fra svaret
  5. Oppdater TripPin.Feed for å bruke de nye sideleserfunksjonene

Merk

Som nevnt tidligere i denne opplæringen, varierer sidevekslingslogikken mellom datakilder. Implementeringen her prøver å dele opp logikken i funksjoner som skal kunne brukes på nytt for kilder som bruker neste koblinger som returneres i svaret.

Table.GenerateByPage

Hvis du vil kombinere (potensielt) flere sider som returneres av kilden i én enkelt tabell, bruker Table.GenerateByPagevi . Denne funksjonen tar som argument en getNextPage funksjon som bør gjøre akkurat det navnet antyder: hente neste side med data. Table.GenerateByPage vil gjentatte ganger kalle getNextPage funksjonen, hver gang resultatene ble gitt forrige gang den ble kalt, til den returnerer null for å signalisere tilbake at ingen flere sider er tilgjengelige.

Siden denne funksjonen ikke er en del av Power Querys standardbibliotek, må du kopiere kildekoden til PQ-filen.

Brødteksten i GetAllPagesByNextLink funksjonen implementerer funksjonsargumentet getNextPage for Table.GenerateByPage. Det vil kalle GetPage funksjonen, og hente nettadressen for neste side med data fra NextLink feltet i meta posten fra forrige samtale.

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

Implementere GetPage

Funksjonen GetPage bruker Web.Contents til å hente én enkelt side med data fra TripPin-tjenesten, og konvertere svaret til en tabell. Det sender svaret fra Web.Contents til GetNextLink funksjonen for å trekke ut nettadressen til neste side, og angir det meta på posten i den returnerte tabellen (side med data).

Denne implementeringen er en litt endret versjon av TripPin.Feed kallet fra de forrige opplæringene.

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];

Funksjonen GetNextLink kontrollerer ganske enkelt brødteksten i svaret for et @odata.nextLink felt, og returnerer verdien.

// 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");

Sette alt sammen

Det siste trinnet for å implementere sidevekslingslogikken er å oppdatere TripPin.Feed for å bruke de nye funksjonene. For øyeblikket ringer du ganske enkelt til GetAllPagesByNextLink, men i etterfølgende opplæringer skal du legge til nye funksjoner (for eksempel å fremtvinge et skjema og spørringsparameterlogikk).

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

Hvis du kjører den samme testspørringen på nytt fra tidligere i opplæringen, skal du nå se sideleseren i aksjon. Du bør også se at du har 24 rader i svaret i stedet for åtte.

QueryWithPaging.

Hvis du ser på forespørslene i fiddler, skal du nå se separate forespørsler for hver side med data.

Fiddler.

Merk

Du vil legge merke til dupliserte forespørsler for den første siden med data fra tjenesten, som ikke er ideelt. Den ekstra forespørselen er et resultat av M-motorens virkemåte for skjemakontroll. Ignorer dette problemet for øyeblikket, og løs det i neste opplæring, der du bruker et eksplisitt skjema.

Konklusjon

Denne leksjonen viste deg hvordan du implementerer pagineringsstøtte for en rest-API. Selv om logikken sannsynligvis vil variere mellom API-er, bør mønsteret som er etablert her, kunne brukes på nytt med mindre modifikasjoner.

I neste leksjon skal du se på hvordan du bruker et eksplisitt skjema på dataene, og går utover de enkle text og number datatypene du får fra Json.Document.

Neste trinn

TripPin Del 6 - Skjema