Delen via


TripPin deel 5 - Paging

Deze meerdelige zelfstudie bevat informatie over het maken van een nieuwe gegevensbronextensie voor Power Query. De zelfstudie is bedoeld om opeenvolgend te worden uitgevoerd. Elke les bouwt voort op de connector die in de vorige lessen is gemaakt, en voegt incrementeel nieuwe mogelijkheden toe aan uw connector.

In deze les gaat u het volgende doen:

  • Ondersteuning voor paging toevoegen aan de connector

Veel REST API's retourneren gegevens in 'pagina's', waarbij clients meerdere aanvragen moeten indienen om de resultaten samen te voegen. Hoewel er enkele algemene conventies zijn voor paginering (zoals RFC 5988), varieert het over het algemeen van API tot API. Gelukkig is TripPin een OData-service en de OData-standaard definieert een manier om paginering uit te voeren met behulp van odata.nextLink-waarden die worden geretourneerd in de hoofdtekst van het antwoord.

Om eerdere iteraties van de connector te vereenvoudigen, was de TripPin.Feed functie niet paginabewust. Het parseert gewoon elke JSON die is geretourneerd uit de aanvraag en heeft deze opgemaakt als een tabel. Degenen die bekend zijn met het OData-protocol hebben mogelijk gemerkt dat er veel onjuiste veronderstellingen zijn gemaakt in de indeling van het antwoord (zoals ervan uitgaande dat er een veld is dat een value matrix met records bevat).

In deze les verbetert u uw reactieafhandelingslogica door deze paginabewust te maken. Toekomstige zelfstudies maken de logica voor paginaafhandeling robuuster en kunnen meerdere antwoordindelingen verwerken (inclusief fouten van de service).

Notitie

U hoeft uw eigen paginglogica niet te implementeren met connectors op basis van OData.Feed, omdat deze alles automatisch voor u afhandelt.

Controlelijst voor paging

Wanneer u paging-ondersteuning implementeert, moet u de volgende dingen over uw API weten:

  • Hoe vraagt u de volgende pagina met gegevens aan?
  • Omvat het pagingmechanisme het berekenen van waarden, of extraheert u de URL voor de volgende pagina uit het antwoord?
  • Hoe weet u wanneer u wilt stoppen met paging?
  • Zijn er parameters met betrekking tot paging waar u rekening mee moet houden? (zoals 'paginaformaat')

Het antwoord op deze vragen heeft invloed op de manier waarop u de pagineringslogica implementeert. Hoewel er enige hoeveelheid code opnieuw wordt gebruikt in paging-implementaties (zoals het gebruik van Table.GenerateByPage, hebben de meeste connectors uiteindelijk aangepaste logica nodig.

Notitie

Deze les bevat paginglogica voor een OData-service, die een specifieke indeling volgt. Raadpleeg de documentatie voor uw API om de wijzigingen te bepalen die u in uw connector moet aanbrengen om de paging-indeling te ondersteunen.

Overzicht van OData Paging

OData-paging wordt aangestuurd door nextLink-aantekeningen in de nettolading van het antwoord. De waarde nextLink bevat de URL naar de volgende pagina met gegevens. U weet of er nog een pagina met gegevens is door te zoeken naar een odata.nextLink veld in het buitenste object in het antwoord. Als er geen odata.nextLink veld is, hebt u al uw gegevens gelezen.

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

Sommige OData-services bieden clients de mogelijkheid om een voorkeur voor maximale paginagrootte te leveren, maar het is aan de service of deze al dan niet moet worden uitgevoerd. Power Query moet antwoorden van elke grootte kunnen verwerken, dus u hoeft zich geen zorgen te maken over het opgeven van een voorkeur voor paginaformaat. U kunt ondersteuning bieden voor alles wat de service u genereert.

Meer informatie over servergestuurde paging vindt u in de OData-specificatie.

TripPin testen

Controleer voordat u de paging-implementatie herstelt het huidige gedrag van de extensie uit de vorige zelfstudie. Met de volgende testquery wordt de Mensen tabel opgehaald en een indexkolom toegevoegd om het huidige aantal rijen weer te geven.

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

Schakel Fiddler in en voer de query uit in de Power Query SDK. De query retourneert een tabel met acht rijen (index 0 tot 7).

QueryWithoutPaging.

Als u de hoofdtekst van het antwoord van fiddler bekijkt, ziet u dat het in feite een @odata.nextLink veld bevat, wat aangeeft dat er meer pagina's met gegevens beschikbaar zijn.

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

Paging implementeren voor TripPin

U gaat nu de volgende wijzigingen aanbrengen in uw extensie:

  1. De algemene Table.GenerateByPage functie importeren
  2. GetAllPagesByNextLink Een functie toevoegen die wordt gebruikt Table.GenerateByPage om alle pagina's aan elkaar te lijmen
  3. GetPage Een functie toevoegen die één pagina met gegevens kan lezen
  4. GetNextLink Een functie toevoegen om de volgende URL uit het antwoord te extraheren
  5. Bijwerken TripPin.Feed om de nieuwe paginalezerfuncties te gebruiken

Notitie

Zoals eerder in deze zelfstudie is aangegeven, varieert de paginglogica tussen gegevensbronnen. De implementatie hier probeert de logica op te splitsen in functies die herbruikbaar moeten zijn voor bronnen die gebruikmaken van de volgende koppelingen die in het antwoord worden geretourneerd.

Table.GenerateByPage

Als u de (mogelijk) meerdere pagina's wilt combineren die door de bron in één tabel worden geretourneerd, gebruiken Table.GenerateByPagewe . Deze functie krijgt als argument een getNextPage functie die precies moet doen wat de naam voorstelt: de volgende pagina met gegevens ophalen. Table.GenerateByPage roept de getNextPage functie herhaaldelijk aan, telkens wanneer de resultaten worden doorgegeven die de laatste keer zijn aangeroepen, totdat deze terugkeert null om aan te geven dat er geen pagina's meer beschikbaar zijn.

Omdat deze functie geen deel uitmaakt van de standaardbibliotheek van Power Query, moet u de broncode naar uw .pq-bestand kopiëren.

De hoofdtekst van uw GetAllPagesByNextLink functie implementeert het getNextPage functieargument voor Table.GenerateByPage. Hiermee wordt de GetPage functie aangeroepen en wordt de URL opgehaald voor de volgende pagina met gegevens uit het NextLink veld van de meta record uit de vorige aanroep.

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

GetPage implementeren

Uw GetPage functie gebruikt Web.Contents om één pagina met gegevens op te halen uit de TripPin-service en het antwoord te converteren naar een tabel. Hiermee wordt het antwoord van Web.Contents doorgegeven aan de GetNextLink functie om de URL van de volgende pagina te extraheren en ingesteld op de meta record van de geretourneerde tabel (pagina met gegevens).

Deze implementatie is een enigszins gewijzigde versie van de TripPin.Feed aanroep uit de vorige zelfstudies.

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

De GetNextLink functie controleert gewoon de hoofdtekst van het antwoord op een @odata.nextLink veld en retourneert de waarde.

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

Alles samenvoegen

De laatste stap voor het implementeren van de paginglogica is het bijwerken TripPin.Feed van de nieuwe functies. Voor nu hoeft u alleen maar door te bellen naar GetAllPagesByNextLink, maar in de volgende zelfstudies voegt u nieuwe mogelijkheden toe (zoals het afdwingen van een schema en logica voor queryparameters).

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

Als u dezelfde testquery van eerder in de zelfstudie opnieuw uitvoert, ziet u nu de paginalezer in actie. U ziet ook dat u 24 rijen in het antwoord hebt in plaats van acht.

QueryWithPaging.

Als u de aanvragen in Fiddler bekijkt, ziet u nu afzonderlijke aanvragen voor elke pagina met gegevens.

Fiddler.

Notitie

U ziet dubbele aanvragen voor de eerste pagina met gegevens van de service, wat niet ideaal is. De extra aanvraag is het gevolg van het schemacontrolegedrag van de M-engine. Negeer dit probleem voorlopig en los dit op in de volgende zelfstudie, waar u een expliciet schema toepast.

Conclusie

In deze les hebt u geleerd hoe u pagineringsondersteuning voor een Rest API implementeert. Hoewel de logica waarschijnlijk varieert tussen API's, moet het hier vastgestelde patroon opnieuw worden gebruikt met kleine wijzigingen.

In de volgende les bekijkt u hoe u een expliciet schema toepast op uw gegevens, wat verder gaat dan de eenvoudige text en number gegevenstypen waaruit Json.Documentu krijgt.

Volgende stappen

TripPin deel 6 - Schema