Suche, Filter, Sortierung, Pagination
Kurzantwort: Der parameter-Block eines RestListPayload steuert die Suche.
Er besteht aus query (verschachtelte AND/OR-Gruppen aus Filtern), order,
page, limit und meta. CDMS übersetzt das in Criteria-Prädikate und ergänzt
automatisch die Sicherheitsfilter (Owner, Attributfilter), die nicht umgangen
werden können.
{ "response": ["id", "name"], "parameter": { "meta": true, "page": 0, "limit": 25, "order": [{"field": "name", "order": "ASC"}], "query": { "type": "AND", "filter": [ {"key": "status", "value": "ACTIVE", "param": "EQ"}, {"key": "name", "value": "Muster", "param": "LIKE"} ], "group": [ { "type": "OR", "filter": [ {"key": "customer.city", "value": "Berlin", "param": "EQ"}, {"key": "customer.city", "value": "Hamburg", "param": "EQ"} ] } ] } }}| Feld | Typ | Standard | Bedeutung |
|---|---|---|---|
meta | boolean | true | Gesamtzahl der Treffer ermitteln |
page | int | 0 | Seite, nullbasiert |
limit | int | -1 | Seitengröße; -1 = keine Begrenzung |
order | Liste | null | Sortierung, mehrere Kriterien möglich |
query | Gruppe | null | Filterbaum |
Filteroperatoren
Abschnitt betitelt „Filteroperatoren“| Operator | Bedeutung |
|---|---|
EQ | gleich |
NEQ | ungleich |
LIKE | enthält (Standard, wenn kein Operator angegeben ist) |
IN | in der kommaseparierten Werteliste |
ISNULL / ISNOTNULL | leer / nicht leer |
BEFORE / SAMEORBEFORE | Datum vor / vor oder gleich |
AFTER / SAMEORAFTER | Datum nach / nach oder gleich |
MEMBEROF | die Sammlung des Objekts enthält das genannte Element |
Besonderheit MEMBEROF
Abschnitt betitelt „Besonderheit MEMBEROF“Wird als korrelierte EXISTS-Unterabfrage gebaut, nicht als Join. Ein Inner
Join würde Objekte mit leerer Sammlung aus einem OR-Zweig entfernen, ein Left
Join würde Objekte um die Größe ihrer Sammlung vervielfachen. Elemente werden
bei Entity-Sammlungen über id adressiert, bei String-Sammlungen über den Wert.
Andere Elementtypen oder der Operator auf einem Nicht-Sammlungsfeld werden als
Bad Request abgelehnt.
Gruppen und Verschachtelung
Abschnitt betitelt „Gruppen und Verschachtelung“flowchart TB
R["query (type: AND)"] --> F1["filter: status EQ ACTIVE"]
R --> F2["filter: name LIKE Muster"]
R --> G1["group (type: OR)"]
G1 --> F3["filter: city EQ Berlin"]
G1 --> F4["filter: city EQ Hamburg"]
R --> SEC["+ automatisch:<br/>_userId EQ <Benutzer><br/>+ Attributfilter"]
filter und group einer Gruppe werden mit dem type der Gruppe (AND oder
OR) verknüpft. Gruppen sind beliebig tief schachtelbar. Standard von type
ist OR – wer AND will, muss es hinschreiben.
CDMS baut die Wurzel immer selbst: Ist die Client-Query kein AND-Baum, wird sie
als Untergruppe eingehängt. Danach kommen die Sicherheitsfilter mit AND dazu.
Pfadausdrücke
Abschnitt betitelt „Pfadausdrücke“Filter- und Sortierschlüssel dürfen über Beziehungen laufen:
{"key": "customer.address.city", "value": "Berlin", "param": "EQ"}Jede Ebene wird als LEFT JOIN angebunden, damit Objekte ohne Beziehung nicht
aus dem Ergebnis fallen.
Sortierung
Abschnitt betitelt „Sortierung“"order": [ {"field": "customer.name", "order": "ASC"}, {"field": "createdOn", "order": "DESC"}]order kennt ASC, DESC und NONE. Ein ungültiger Pfad führt zu 400.
Pagination und Trefferzahl
Abschnitt betitelt „Pagination und Trefferzahl“setFirstResult(page * limit),setMaxResults(limit)limit = -1schaltet die Begrenzung ab (das Frontend nutzt das für den Item-Baum, der komplett in einem Read kommt)- die Gesamtzahl kommt aus einer separaten Count-Abfrage mit derselben
Filterlogik und landet in
meta.totalCount - bei abstrakten Modellen wird die Trefferzahl über die konkreten Untertypen summiert, damit deren jeweilige Filter gelten
Automatische Sicherheitsfilter
Abschnitt betitelt „Automatische Sicherheitsfilter“Vor jeder Abfrage ergänzt der System-Layer:
| Filter | wann |
|---|---|
_userId EQ <aktueller Benutzer> | Modell erbt von AbstractUserModel |
| Attributfilter | für jeden registrierten CdmsFilterInterface-Bean des Modells |
Beide sind als mandatory markiert: Lässt sich ein solcher Filter nicht in ein Datenbank-Prädikat übersetzen, scheitert die Abfrage – sie wird nicht stillschweigend weggelassen. Ein weggelassener Sicherheitsfilter würde alle Zeilen liefern statt der erlaubten Teilmenge.
Der Mandantenfilter selbst taucht hier nicht auf: Er entsteht durch die Wahl der Datenbank, siehe Mandantentrennung.
Fehlerverhalten bei kaputten Filtern
Abschnitt betitelt „Fehlerverhalten bei kaputten Filtern“| Situation | Ergebnis |
|---|---|
fehlender key oder fehlender Operator | 400 ApiBadRequestException |
| unbekanntes Feld | 500 SystemConfigurationException |
| ungültige UUID als Wert | 400 DatabaseConstraintViolationException |
| ungültiger Sortierpfad | 400 |
Kein Filter wird still ignoriert – das ist Absicht: ein verschluckter Filter liefert zu viele Daten.
Filter in verschachtelten Anfragen
Abschnitt betitelt „Filter in verschachtelten Anfragen“Auch Listenreferenzen im Response Request nehmen einen parameter-Block; siehe
Response Requests. CDMS ergänzt dort automatisch den
Filter auf die Rückreferenz.
Datums- und Zeitformate
Abschnitt betitelt „Datums- und Zeitformate“Werte in Filtern werden über die Muster app.format.datetime,
app.format.date und app.format.time geparst (Standards:
yyyy-MM-dd HH:mm:ss, yyyy-MM-dd, HH:mm:ss).