Alle REST-Endpunkte von Personyze nutzen dieselbe Syntax für Pfadparameter, um zu filtern, Spalten auszuwählen, zu sortieren und Ergebnisse zu begrenzen. Dieselben Modifikatoren — where, columns, column, order_by, order_by_desc, limit — funktionieren einheitlich für alle Objekte, dazu eine Kurzform für Abfragen per Primärschlüssel.
Voraussetzungen: REST-API: Überblick und Authentifizierung — dort werden URL-Aufbau und Zugangsdaten erklärt.
Allgemeiner Aufbau der URL
Nach dem Objektnamen ist der URL-Pfad eine Folge von /<modifier>/<value>/... -Paaren:
/rest/<object>/[<id>|]<modifier>/<value>/<modifier>/<value>/...
Hinweise:
- Die Reihenfolge spielt keine Rolle.
/limit/100/where/x=yist gleichwertig mit/where/x=y/limit/100. - Jeder Modifikator erscheint höchstens einmal pro Anfrage. Mehrere
where-Bedingungen stehen in einem einzigenwhere/-Segment, verbunden mit&und|-Operatoren (siehe unten). - Werte werden vor dem Parsen URL-dekodiert — ein Spaltenwert, der
/,=,&oder%enthält, muss daher prozentkodiert werden.
Form mit einzelner ID (Abfrage per Primärschlüssel)
Ein reines numerisches Segment an erster Stelle ist eine Abfrage per Primärschlüssel:
GET /rest/<object>/<id>
Das liefert einen Datensatz (ein Objekt, kein Array mit einem Element) oder 400 Row not found , wenn die ID nicht existiert.
GET /rest/placeholders/14
GET /rest/users/57291 # PK = user_id
Für Abfragen per externer Kennung (Ihre SKU, CRM-ID usw.) nutzen Sie die where -Form mit internal_id:
GET /rest/users/where/internal_id=42
GET /rest/products/where/internal_id=SKU-1234
where — filtern
Filtert die Ergebnismenge. Die einfachste Form ist where/<column><op><value>:
| Operator | Bedeutung | Beispiel |
|---|---|---|
= |
gleich | where/status=active |
!= |
ungleich | where/status!=draft |
> |
größer als | where/last_session_time>1700000000 |
>= |
größer oder gleich | where/age_from>=18 |
< |
kleiner als | where/time<1700000000 |
<= |
kleiner oder gleich | where/age_to<=65 |
: |
in (Kommaliste) | where/id:1,2,3,4 |
!: |
nicht in | where/status!:draft,archived |
Bedingungen verknüpfen mit & (UND) und | (ODER)
where/<cond1>&<cond2> # both must match (AND)
where/<cond1>|<cond2> # either matches (OR)
where/<a>&<b>|<c>&<d> # (a AND b) OR (c AND d) — & binds tighter than |
Beispiele:
where/status=active&age_from>=18
where/email=alice@example.com|email=bob@example.com
where/category:books,tools&is_in_stock=yes
Anforderung an indexierte Spalten
REST-Endpunkte, die große Tabellen umfassen (users, events, sessions_archive, summary_actionsusw.), lehnen Abfragen ab, deren where oder order_by keinen Index nutzt. Die Fehlermeldung nennt die indexierten Spalten, die der Endpunkt anbietet:
Cannot do this operation on whole table: column "uset_id" is not indexed.
Please, use "where" condition or order by an indexed column
(user_id, last_session_time, data_last_modified, fb_id, email, internal_id).
Zusammengesetzte Indizes erscheinen in der Form [col1, col2, col3] . Nur die führende Spalte eines zusammengesetzten Index ist als einzelner Filter nutzbar:
... or order by an indexed column
(user_id, [product_internal_id, user_id, transaction_time], status, time).
Hier nutzt where/product_internal_id=... den zusammengesetzten Index, where/transaction_time>... allein dagegen nicht — sie ist die dritte Spalte des Index und nur zusammen mit product_internal_id und user_id.
columns — bestimmte Spalten auswählen
Schränkt die ausgegebenen Spalten ein. Durch Kommas getrennte Liste. Standard sind „alle dokumentierten Spalten“ des Objekts.
GET /rest/users/where/internal_id=42/columns/user_id,first_name,last_name
Unbekannte Spalten: Bei Objekten, die dynamische Spaltennamen unterstützen (users, articles, products), werden unbekannte Spalten als nullzurückgegeben. Bei Objekten mit festem Schema erhalten Sie 400 Unknown column.
column (Singular) — flaches Array von Werten
Kurzform für „eine Spalte auswählen, ein flaches Array von Werten zurückgeben“ statt eines Arrays von Objekten.
GET /rest/users/where/last_session_time>1700000000/column/email
→ ["alice@example.com", "bob@example.com", ...]
Im Vergleich zur Pluralform columns :
GET /rest/users/where/last_session_time>1700000000/columns/email
→ [{"email":"alice@example.com"}, {"email":"bob@example.com"}, ...]
Nützlich, wenn Sie das Ergebnis direkt in ein anderes System einspeisen möchten, das eine Liste erwartet (z. B. beim Export einer Zielgruppe oder beim Deduplizieren von E-Mail-Adressen).
order_by / order_by_desc
order_by/<col>[,<col>...] # ascending
order_by_desc/<col>[,<col>...] # descending
Mehrere Spalten: Gleichstände in der ersten Spalte werden durch die zweite aufgelöst usw. Jede Richtung (order_by oder order_by_desc) gilt für alle aufgeführten Spalten.
GET /rest/users/order_by_desc/last_session_time/limit/100
Die erste aufgeführte Spalte muss eine indexierte Spalte sein (oder die führende Spalte eines zusammengesetzten Index), wenn es keine where -Klausel gibt — sonst lehnt der Endpunkt die Anfrage als vollständigen Tabellenscan ab.
limit — Paginierung
limit/<count> # first <count> rows
limit/<offset>,<count> # skip <offset> then take <count>
Die feste Obergrenze liegt bei 1.000 Zeilen pro Anfrage. Größere Werte werden abgelehnt mit 400 Only can select up to 1000 rows.
GET /rest/users/order_by_desc/last_session_time/limit/100
GET /rest/users/order_by_desc/last_session_time/limit/100,100 # rows 100..199
Cursor-Paginierung — empfohlen für große Ergebnismengen
Tiefe offset -Werte werden langsam, weil die Datenbank alle übersprungenen Zeilen erneut lesen muss. Paginieren Sie bei größeren Ergebnismengen, indem Sie die indexierte order_by -Spalte durchlaufen, mit cursorartigen where:
# page 1
GET /rest/users/order_by_desc/last_session_time/limit/1000
# page 2 — pass the last seen value
GET /rest/users/where/last_session_time<1730000000/order_by_desc/last_session_time/limit/1000
# page 3 — pass the last seen value from page 2
GET /rest/users/where/last_session_time<1729000000/order_by_desc/last_session_time/limit/1000
Der Cursorwert ist der Wert, den der letzte Datensatz der vorigen Seite in der indexierten Spalte hatte. Das bleibt dauerhaft schnell — jede Seite ist ein indexierter Bereichsscan, kein linearer Scan, der „50.000 Zeilen überspringt“.
< statt <=) plus ein Unterscheidungsmerkmal auf einer eindeutigen Spalte — z. B. where/last_session_time<X&user_id<Y.Alles zusammen
GET /rest/products
/where/category=tools&is_in_stock=yes
/columns/id,internal_id,title,price,inventory
/order_by/title
/limit/100
(Zeilenumbrüche nur zur besseren Lesbarkeit — tatsächlich steht alles in einer Zeile, ohne Leerzeichen.)