Zum Inhalt springen

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"}
]
}
]
}
}
}
FeldTypStandardBedeutung
metabooleantrueGesamtzahl der Treffer ermitteln
pageint0Seite, nullbasiert
limitint-1Seitengröße; -1 = keine Begrenzung
orderListenullSortierung, mehrere Kriterien möglich
queryGruppenullFilterbaum
OperatorBedeutung
EQgleich
NEQungleich
LIKEenthält (Standard, wenn kein Operator angegeben ist)
INin der kommaseparierten Werteliste
ISNULL / ISNOTNULLleer / nicht leer
BEFORE / SAMEORBEFOREDatum vor / vor oder gleich
AFTER / SAMEORAFTERDatum nach / nach oder gleich
MEMBEROFdie Sammlung des Objekts enthält das genannte Element

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.

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 &lt;Benutzer&gt;<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.

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.

"order": [
{"field": "customer.name", "order": "ASC"},
{"field": "createdOn", "order": "DESC"}
]

order kennt ASC, DESC und NONE. Ein ungültiger Pfad führt zu 400.

  • setFirstResult(page * limit), setMaxResults(limit)
  • limit = -1 schaltet 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

Vor jeder Abfrage ergänzt der System-Layer:

Filterwann
_userId EQ <aktueller Benutzer>Modell erbt von AbstractUserModel
Attributfilterfü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.

SituationErgebnis
fehlender key oder fehlender Operator400 ApiBadRequestException
unbekanntes Feld500 SystemConfigurationException
ungültige UUID als Wert400 DatabaseConstraintViolationException
ungültiger Sortierpfad400

Kein Filter wird still ignoriert – das ist Absicht: ein verschluckter Filter liefert zu viele Daten.

Auch Listenreferenzen im Response Request nehmen einen parameter-Block; siehe Response Requests. CDMS ergänzt dort automatisch den Filter auf die Rückreferenz.

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).