API Paging/Pagination - Tutorial

Last Update: 04.12.2023

Was ist Paging/Pagination?


Paging beschreibt im Allgemeinen eine Nummerierung der Seiten, die sich in der Regel oben oder unten auf den Seiten der Website befindet (Google Suchergebnisse). API Paging ist nichts anderes, als die Abfrage aller Datensätze pro Seite anhand eines HTTP-Requests.

Es wird in Umgebungen eingesetzt, in denen viele Datensätze zur Verfügung gestellt oder abgeholt werden können und sorgt dafür, Ergebnislisten in überschaubare Abschnitte zu unterteilen. Je nach Implementierung kann es verschiedene Arten von Paging geben. Wir gehen dabei auf die beiden gängigsten Varianten ein.

Eine ausführliche Beschreibung und weitere Varianten sind hier zu finden: https://dev.to/pragativerma18/unlocking-the-power-of-api-pagination-best-practices-and-strategies-4b49

Generelles Setup


Mit der Version 4.6.6 gibt es eine neue Checkbox im zeitgesteuerten HTTP-Eingangsagenten (Paging aktivieren). Damit ist Paging innerhalb eines Profils möglich, ohne, dass ein Vorprofil benötigt wird.

Voraussetzung ist, dass die Variable VAR_SYS_HTTP_PAGING_URL in Phase 3 gefüllt wird. Diese wird verwendet, um das Profil so lange erneut aufzurufen, bis keine Eingangsdaten mehr zurück geliefert werden.

Verwendung

Cursor-Paging: EMPFOHLEN - da nur synchroner Aufruf möglich.

Offset-Paging: NACH ERMESSEN - der Offset kann auch mittels Logik in Phase 3 berechnet werden, für größere Datenmengen eignet sich bei Offset-Paging weiterhin eher die asynchrone Profilkette (Beispiel unten), welche eine Parallelverarbeitung durchführt.

Beispiel-Profil: Profile-paging_checkbox_phase1.pak

Hinweis: Der Aufruf der Profile mit aktiver Paging-Checkbox erfolgt synchron!

Offset-Paging


Beim Offset-Paging sind die zu ermittelnden Daten durch limit und offset begrenzt. Das limit hat dabei ein fest definiertes Maximum (bei Spotify 50).

Beispiel: https://api.spotify.com/v1/artists/43ZHCT0cAZBISjO8DG9PnE/albums?include_groups=single&market=US&limit=50&offset=0

Die Spotify-API liefert uns damit 50 Michael Jackson Alben (bzw. die erste Page).

Response
{
"href": "https://api.spotify.com/v1/artists/3fMbdgg4jU18AjLCKBhRSm/albums?include_groups=album,single,compilation,appears_on&offset=0&limit=1&market=DE&locale=de,en-US;q=0.7,en;q=0.3",
"limit": 50,
"next": "https://api.spotify.com/v1/artists/3fMbdgg4jU18AjLCKBhRSm/albums?include_groups=album,single,compilation,appears_on&offset=1&limit=1&market=DE&locale=de,en-US;q=0.7,en;q=0.3",
"offset": 0,
"previous": null,
"total": 274,
"items": [
....data details (cut off)...
]
}

In der Response erkennt man, dass ein Key-Value total enthalten ist (Zeile 7), welcher angibt, wie viele Datensätze existieren.

Möchten wir alle Datensätze abfragen, können wir total durch das limit teilen, um die Anzahl der benötigten Requests zu erhalten: 274 / 50 = 5,48

Um alle Alben zu erhalten, benötigen wir also 6 Requests.

Setup in Profilen


Es gibt mehrere Möglichkeiten dies umzusetzen:

  • Profilkette - schnell und effizient
    Im ersten Profil wird ein einzelner Request durchgeführt, damit die Gesamtzahl der Requests berechnet werden kann. Anschließend wird der Offset für jede Iteration berechnet und das Datenprofil getriggert.
    Beispiel-Profile: Profile-paging_tutorial_start_profile.pak und Profile-paging_tutorial_write_data.pak. Achtung: Das Profil paging_tutorial_write_data wird asynchron (sehr schnell parallel) getriggert, was bei manchen APIs zu Rate-Limitations, bzw. bei Firewalls gegebenenfalls zu Intrusion-Detection führen kann!

  • Einzelprofil - für kleinere Datenmengen
    Punkt 1 lässt sich auch innerhalb eines Profils mittels der HTTP-Funktion umsetzen. Dies eignet sich aufgrund des komplexen Mappings meist nur für kleinere Datenmengen!

Cursor-Paging


Cursor-Paging verhält sich etwas anders als das Offset-Paging. Die nächste Page wird durch einen Folgelink bzw. UniqueID oder Token im vorherigen Request mitgegeben und kann nicht per Query-Parameter im Voraus berechnet werden.

Beispiel: https://graph.microsoft.com/v1.0/users?$top=2

Die Microsoft Graph API liefert uns damit zwei Microsoft Benutzer pro Page.


Response
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users",
"@odata.nextLink": "https://graph.microsoft.com/v1.0/users?$top=2&$skiptoken=RFNwdAIAAQAAACs6YWRtX3NjaG90d...i00MmQ5LTkxMTQtYzNkMDMxMGY1YWRjuQAAAAAAAAAAAAA",
"@microsoft.graph.tips": "This request only returns a subset of the resource's properties. Your app will need to use $select to return non-default properties. ...",
"value": [
{
"businessPhones": [],
"displayName": "Daniel Mueller(ADM-Account)",
"givenName": "Daniel",
"jobTitle": null,
"mail": null,
"mobilePhone": null,
"officeLocation": null,
"preferredLanguage": null,
"surname": "Mueller",
"userPrincipalName": "adm_kaufmann@xxxxxx.onmicrosoft.com",
"id": "f33db0bc-e5bf-4f39-bec7-e55aa2c60169"
},
{
"businessPhones": [],
"displayName": "Andreas Meier(admin)",
"givenName": "Andreas",
"jobTitle": null,
"mail": null,
"mobilePhone": null,
"officeLocation": null,
"preferredLanguage": null,
"surname": "Meier",
"userPrincipalName": "adm_schott@xxxxxx.onmicrosoft.com",
"id": "c6e4974c-f1a2-42d9-9122-c3d0310d5adc"
}
]
}


In Zeile 3 der Response erhalten wir ein Key Value @odata.nextLink zurück. Das ist ein automatisch generierter Link, welcher die darauf folgenden zwei Datensätze zurückgibt.

Die Folgelinks werden so lange als Response zurückgegeben, bis der letzte Datensatz abgefragt wurde.

Um bei dieser Methode alle Datensätze zu erhalten, müssen wir die Folgelinks von @odata.nextLink so oft aufrufen, bis kein Key Value @odata.nextLink mehr in der JSON-Response enthalten ist, bzw. der Wert leer ist.

Setup in Profilen


Es gibt mehrere Möglichkeiten dies umzusetzen:

  • Profilkette - schnell und effizient
    Im ersten Profil wird ein einzelner Request durchgeführt, welcher nur die URL an das Folgeprofil übergibt. Das Folgeprofil ruft sich selbst im Antwortweg auf und übergibt sich automatisch die neue Variable für Phase 1.
    In Phase 3 wird der Wert von @odata.nextLink überprüft und bei leerem Inhalt der letzte Job ohne Fehler mittels abort-Funktion abgebrochen.
    Beispiel-Profile: Profile-paging_tutorial_start_graph_api.pak und Profile-paging_tutorial_graph_api.pak.
    Achtung: Profil-Loops können als Endlosschleife sehr schnell zu einem Absturz führen, wenn sie nicht korrekt beendet werden oder die Logik fehlerhaft ist. Bitte testen Sie vorher mit einzelnen Requests, ob die abort-Logik korrekt funktioniert!

  • Einzelprofil - für kleinere Datenmengen
    Punkt 1 lässt sich auch innerhalb eines Profils mittels der HTTP-Funktion umsetzen. Dies eignet sich aufgrund des komplexen Mappings meist nur für kleinere Datenmengen! Vorteil: Es wird kein Profil-Loop benötigt und ist deshalb etwas sicherer umzusetzen.