CodamAIDocs
Themafertig

UND/ODER-Gruppen

Wie type, filter und group einen Filterbaum bilden, warum der Standard ODER ist und wie aus dem Baum eine Bedingung wird.

Ausprägungen
eine Gruppe ANDeine Gruppe OR (Standard)verschachtelte GruppenODER-Gruppe mit filter und groupvergessenes typeleere Gruppe

Worum es geht

Eine Suche hat selten nur eine Bedingung. „Kunden aus Köln und mit offenem Auftrag“, „Name enthält Muster oder E-Mail enthält Muster“. Dafür ist query ein Baum aus Gruppen:

{
  "type": "AND",
  "filter": [ …Bedingungen… ],
  "group":  [ …Untergruppen, jede wieder mit type, filter, group… ]
}
SchlüsselBedeutung
typeAND: alle Einträge müssen zutreffen. OR: mindestens einer.
filtereinzelne Bedingungen, siehe Operatoren
groupUntergruppen, beliebig tief

Vom Baum zur Formel

flowchart TB
    R["AND"] --> F1["city = Köln"]
    R --> G["OR"]
    G --> F2["name LIKE %muster%"]
    G --> F3["email LIKE %muster%"]
{
  "type": "AND",
  "filter": [ { "key": "city", "value": "Köln", "param": "EQ" } ],
  "group": [
    {
      "type": "OR",
      "filter": [
        { "key": "name",  "value": "%muster%", "param": "LIKE" },
        { "key": "email", "value": "%muster%", "param": "LIKE" }
      ]
    }
  ]
}

wird zu

city = 'Köln' AND (name LIKE '%muster%' OR email LIKE '%muster%')

Wie CDMS eine Gruppe übersetzt

Aus jeder Gruppe wird eine Bedingung. CDMS verknüpft alle Einträge der Gruppe mit dem type der Gruppe: jeden Filter aus filter und jede Untergruppe aus group. Eine Untergruppe zählt dabei als ein Eintrag, sie steht in Klammern.

flowchart LR
    G["Gruppe mit type T"] --> A["filter A"]
    G --> B["filter B"]
    G --> U["Untergruppe U<br/>(eigener type)"]
    A --> F["A T B T (U)"]
    B --> F
    U --> F

Es spielt also keine Rolle, ob eine Bedingung in filter steht oder als eigene Untergruppe in group. Beides sind gleichrangige Einträge der Gruppe:

Du schreibstCDMS wertet aus
{ "type": "OR", "filter": [A, B] }A OR B
{ "type": "OR", "filter": [A], "group": [ { "type": "AND", "filter": [B, C] } ] }A OR (B AND C)
{ "type": "OR", "group": [ { "type": "AND", "filter": [A] }, { "type": "AND", "filter": [B, C] } ] }A OR (B AND C), dasselbe wie darüber
{ "type": "AND", "filter": [A], "group": [ { "type": "OR", "filter": [B, C] } ] }A AND (B OR C)

Eine leere Untergruppe ("filter": [], "group": []) lässt CDMS weg. Sie schränkt nichts ein und macht aus einer ODER-Gruppe auch kein „alles“.

Alle Ausprägungen

Gruppen in allen Formen

Wann: Alle Bedingungen müssen zutreffen.

{ "type": "AND", "filter": [ { "key": "city", "value": "Köln", "param": "EQ" }, { "key": "active", "value": "true", "param": "EQ" } ] }

Ergebnis: Aktive Kunden aus Köln.

Wann: Eine Bedingung reicht, z. B. Suche über mehrere Felder.

{ "type": "OR", "filter": [ …name…, …email… ] }

Ergebnis: Kunden, bei denen Name oder E-Mail passt.

Wann: UND und ODER gemischt.

Die äußere Gruppe AND mit den festen Bedingungen in filter, die Alternativen als Untergruppe OR in group. Die Tiefe ist nicht begrenzt.

Ergebnis: city = Köln AND (name … OR email …)

Wann: Du schreibst { "type": "OR", "filter": [A], "group": [G] }.

A und G sind gleichrangige Alternativen. Ist G eine UND-Gruppe, muss G als Ganzes zutreffen.

Ergebnis: A OR (G): alle Objekte, die A erfüllen oder G.

Wann: Du schreibst { "filter": [ …city…, …active… ] } ohne type.

Die Gruppe ist dann ODER. Aus „aktive Kunden aus Köln“ wird „alle aus Köln und alle aktiven“.

Ergebnis: Mehr Treffer als erwartet.

Wann: "query": { "type": "AND", "filter": [], "group": [] } oder "query": null

Eine Gruppe ohne Einträge schränkt nichts ein.

Ergebnis: Alle sichtbaren Objekte.

Die Falle „zu viele Treffer“

Filter city = Köln und active = true, ohne und mit type
typeKunde aus Köln, aktivKunde aus Köln, inaktivKunde aus Bonn, aktivErgebnis
ANDjaneinnein1 Treffer – gemeint
fehlt (= OR)jajaja3 Treffer – zu viele

Deine Gruppe und die Sicherheitsfilter

Dein query ist nie die ganze Bedingung. CDMS setzt eine UND-Wurzel darüber und hängt die Filter an, die immer mitlaufen. Ist dein query eine UND-Gruppe, werden seine Einträge direkt in diese Wurzel übernommen. Ist es eine ODER-Gruppe, wird es als Ganzes eine Untergruppe:

flowchart TB
    W["AND (Wurzel von CDMS)"] --> C["dein query<br/>(bei OR als eigene Untergruppe)"]
    W --> S1["eigene Daten: _userId = du"]
    W --> S2["Attributfilter"]
    W --> S3["eigene Pflichtfilter"]

Dein ODER kann die Sicherheitsfilter deshalb nie aushebeln: Es steht immer neben ihnen, nie über ihnen.

Quellen im Code und in der Wissensdatenbank
  • CDMS/cdms-persistence-database – DatabaseConditionBuilder.addWhere
  • CDMS/cdms-commons – ListSearchLogic (type = OR als Standard)
  • CDMS/cdms-system-layer – AbstractLayer.buildSearchRoot
Suchen