Filter

Der Filteropen in new window gehört mit zu den wichtigsten und am häufigsten benötigten Steps. Mit diesem Step kann man Zeilen aus einem Spreadsheet herausfiltern / entfernen. Dazu definiert man eine Filterbedingung, die beschreibt, welche Zeilen noch im Spreadsheet verbleiben dürfen.

Konfiguration

Der Step kann mit beliebigen anderen Steps verwendet werden, die als Output ebenfalls ein Spreadsheet haben. Meistens findet man diesen Step nach einem Mapper.

Durch Eingabe einer Filterbedingung in Freemarker-Syntax kann man die Zeilen bestimmen, die im Ergebnis-Spreadsheet auftauchen sollen.

Im Beispiel würden alle Zeilen im Ergebnis-Spreadsheet auftauchen, deren Spalte "condition" den Wert "new" enthält.

Statt der manuellen Eingabe, kann auch ein komfortabler Wizzard für die initiale Erstellung des Filterausdrucks genutzt werden.

Dadurch wird z.B. folgender Filterausdruck erzeugt:

Limitierung der Step-Vorschau bei Daten aus Datastore

(Glühbirne) Wenn ein Filter Step Daten aus einem SearchDatastore Step bezieht, dann werden in der Step-Vorschau nur die ersten 100 Zeilen berücksichtigt. Das führt bei der Vorschau des Filters zu dem Phänomen, dass der Filter kein Ergebnis liefert.  D.h. wenn z.B. ein erwarteter Wert erst in Zeile 101 auftaucht, dann wird die Filter-Vorschau diesen Wert nie bekommen und der Filter würde nicht greifen.

Aber: Ein normaler Flow-Durchlauf hat diese Limitierung nicht. Diese Einschränkung ist aus Performance-Gründen in der Step-Vorschau leider nicht anders möglich. ​
Alternative: Zum Testen von Filtern mit vielen Daten kann man sich aber z.B. eine CSV Datei erstellen und mit dem CSVReader statt SearchDatastore Step testen. Der CSVReader hat keine Zeilen-Begrenzung.

Negatives Ergebnis

Wenn man das genaue Gegenteil braucht (im Beispiele "alle Zeilen, wo condition NICHT "new"  bzw. der price <= 50 ist) gibt es einen zweiten Step-Output negativeOutput.
Dieser beinhaltet genau dieses negierte Ergebnis-Spreadsheet.

Vorteil: Man spart sich einen weiteren Filter-Step und der Flow wird übersichtlicher.

Zeilen-Validierung

Es gibt Spreadsheets, die mit Schema-Definitionen (siehe Datastores#Schema) verknüpft sind. Dazu zählen der SearchDatastore oder Mapper SpreadsheetMapper Step. 
Über das Schema kann man für jede Spalte Regeln festlegen (z.B. Datentyp, erlaubte Werte, reguläre Ausdrücke, Beschreibung). Diese Schemainformationen kann man auswerten und entscheiden ob ein einzelnes Feld oder eine ganze Zeile eines Spreadsheets valide ist oder nicht.

Dazu gibt es im Filter jetzt auch Filtermöglichkeiten.

Invalide Zeilen filtern

Um einen Filter auf die ganze Zeile anzuwenden, wählt man in der Filter-Auswahl Zeile und dann bei Zeilen-Operatoren

  • ist valide
  • ist nicht valide

Dadurch wird folgendes Filter-Skript erstellt:

${row.isValid()}

Dieser Filter lässt nur Zeilen durch, deren Spalten alle Validierungsregeln des Schemas erfüllen (z.B. alle Pflichtspalten gefüllt, erlaubte Werte passen usw.)

Alle ungültigen Spalten (d.h. die mindestens einen Fehler enthalten erhält man mit dem negierten Filter):

${!row.isValid()}

Spalten validieren

Das gleiche Prinzip funktioniert auch mit einzelnen Spalten.

Um zum Beispiel nur Zeilen zu erlauben deren Preis-Spalte valide ist, kann man folgenden Filter erstellen:

${price.isValid()}

Hinweis

Die Validierung funktioniert nur, wenn dem Spreadsheet auch ein Schema zugrunde liegt. Das ist nur bei Spreadsheets aus dem SearchDatastore oder Mapper mit Ziel-Schema der Fall.

Erweiterte Optionen

Filter kurzzeitig deaktivieren

Bei der Erstellung der späteren Bearbeitung oder bei der Fehlersuche kommt es häufig vor, dass man einen Filter im Flow gern mal deaktiviert, um zu prüfen, was der Filter so alles wegschneidet, und ob das auch korrekt ist.

Mit der Bypass-Option im Filter kann man die Filterung deaktivieren. D.h. der Step bleibt ganz normal aktiviert, aber die Filterbedingung wird ignoriert. Der Step lässt praktisch den Input ungefiltert durch (Input = Output). 
Im Evenltog taucht dann eine Warnung auf, falls man mal vergisst den Filter wieder zu aktivieren. Zum deaktivieren des Filters stellen Sie bypass=Yes. Standardwert ist No.

CacheMode aktivieren

Die Option cacheMode kann genutzt werden, um das Ergebnis des Filters zwischen zu speichern. Dabei kann man Auswählen ob man nur das positive- oder negative Ergebnis cachen möchte, oder das gesamte Ergebnis. Das kann langsame Flows stark beschleunigen.

Wann sollte das aktiviert werden? Sobald im zwei oder mehr Steps das Filter-Ergebnis verwenden. Dann kann bei diesem Filter der CacheMode aktiviert werde, um die Laufzeit zu verringern.

Hinweis: Bei aktiviertem CacheMode gibt es eine Einschränkung. Der Zugriff von Varianten-Zeilen auf Parent-Zeilen funktioniert, aber der Zugriff von Child-Zeilen auf Master-Zeilen funktioniert nicht.

D.h. man kann ${parent['columnname']} benutzen, jedoch nicht ${master['columnname']}. (Siehe auch Auf Relationen zugreifen). Aus diesem Grund ist der CacheMode standardmäßig deaktiviert.

Cookbook zum Thema CacheMode

Lesen Sie mehr zum Thema im Cookbook Reduzierung von Laufzeiten durch Einsatz vom CacheMode im Mapper und Filteropen in new window

Beispiel 1 - Nach einer Spalte filtern

Gegeben sei folgendes Input-Spreadsheet:

idnamekategoriepreis
1Artikel1Schuhe29.99
2Artikel2Hosen19.99
3Artikel3Hosen39.99

Anforderung: Ich will alle Artikel aus der Kategorie "Hosen".

Filterbedingung: kategorie! == "Hosen"

Ergebnis: Das Spreadsheet nach der Filterung enthält nur Artikel2 und Artikel3

idnamekategoriepreis
2Artikel2Hosen19.99
3Artikel3Hosen39.99

Beispiel 2 - Nach 2 Spalten filtern

Erweitern wir das erste Beispiel und filtern jetzt zusätzlich noch nach der Preisspalte, so dass wir nur Hosen bekommen, die > 20 EUR kosten.

Gegeben sei folgendes Input-Spreadsheet:

idnamekategoriepreis
1Artikel1Schuhe29.99
2Artikel2Hosen19.99
3Artikel3Hosen39.99

Anforderung: Ich will alle Artikel aus der Kategorie "Hosen" die teurer sind als 20 EUR.

Filterbedingung: (kategorie! == "Hosen" && preis?number > 20.00)

Ergebnis: Das Spreadsheet nach der Filterung enthält nur Artikel3, weil das die einzige Hose ist, welche die Bedingung erfüllt.

idnamekategoriepreis
3Artikel3Hosen39.99

Spaltenauswahl statt fester Wert in der Bedingung

Statt feste Zeichenketten in der Bedingung zu verwenden, wie im obigen Beispiel, kann man optional auch auf die Werte von Spalten in der Bedingung zugreifen. Das ist sehr praktisch, wenn man hochdynamische Bedingungen bauen will, die nicht nur auf feste Werte vergleichen, sondern dynamisch mit den Werten aus Spalten im Spreadsheet arbeiten.

Das resultiert in folgender Bedingung.

Hinweis

Man beachte, dass brandname hier nicht in Anführungsstriche eingeschlossen ist. Das bedeutet, dass es kein fester Wert ist (also keine Zeichenkette) sondern eine Variable. In diesem Fall referenziert diese Variable den Wert der Spalte brandname aus dem Input-Spreadsheet. Übersetzt bedeutet obige Bedingung:

Im Input-Spreadsheet gibt es zwei Spalten marke sowie brandname. Der Filter lässt nur Zeilen durch, wenn beide Spalten den gleichen Wert beinhalten.

Dynamischer Spaltenerkennung durch Step-Ergebnisvorschau

Damit der Filter die verfügbaren Spalten für die Filterbedingung anzeigen kann, müssen diese bekannt sein. Das funktionierte in der Vergangenheit nur, wenn das zu filternde Spreadsheet aus einem Mapper SpreadsheetMapper-Step kam. 
War das nicht der Fall, dann konnte man die Spalten nicht in der Spaltenauswahl sehen. 
Problem: Man musste noch einen Mapper einbauen, damit man sich im Filter komfortabel eine Bedingung zusammen klicken konnte.

Mittlerweile geht das auch ohne vorgeschalteten Mapper.

Dazu muss man sich die Ergebnisvorschau des Filters selbst oder des Steps anzeigen lassen, der das Input-Spreadsheet liefert. Sobald die Vorschau einmal angezeigt wurde ist die Spaltenauswahl im Filter auch verfügbar.

Tips und Tricks

Klammern nutzen

Bei komplexeren Bedingungen mit UND und ODER ist es wichtig auf die korrekte Klammersetzung zu achten. Dazu etwas Theorieopen in new window.

lieferbar! == 'Ja' && ( Hersteller! == 'A' || Hersteller! == 'B')

Hier werden alle Datensätze gefunden, die lieferbar sind und entweder von Hersteller A oder B sind.

Was wäre, wenn man die Klammern weglassen würde?

lieferbar! == 'Ja' && Hersteller! == 'A' || Hersteller! == 'B'

Dann würde man Datensätze finden die entweder lieferbar und von Hersteller A sind, oder von Hersteller B. D.h. bei Hersteller B wäre das Feld lieferbar egal (weil UND Vorrang vor ODER hat - siehe Theorieopen in new window). Evtl. ist das aber nicht das was man möchte.

Leerzeichen entfernen

Oft kommt es vor, dass Werte in Spalten noch "unsichtbare" Zeichen z.B. Leerzeichen am Anfang/Ende enthalten. 
Für diesen Fall sollte man Filter etwas fehlertoleranter machen z.B. durch ?trimopen in new window:

lieferbar! == 'Ja' && ( Hersteller!?trim == 'A' || Hersteller!?trim == 'B')

Wann hilft das? Angenommen Spalte Hersteller beinhaltet noch ein Leerzeichen (also "A " statt "A"), dann würde ein exakter Vergleich mit == 'A' nicht klappen. Durch ?trim werden Leerzeichen am Anfang und am Ende weggeschnitten und erst dann verglichen.

Nach Teilzeichenketten suchen

Anstatt dem direkten Vergleich mit einem Wert kann man auch prüfen, ob ein bestimmter Wert enthalten ist. Das kann man mit ?containsopen in new window erreichen.

lieferbar!?trim?contains('Ja') && ( Hersteller!?trim?contains('Marke A') || Hersteller!?trim?contains('Marke B') )

Das ist hilfreich bei folgenden Beispieldaten, wo eher "prosa" in den Spalten steht, statt exakter Werte.

lieferbarHersteller
Ja lieferbarz.B. Marke A
Nein nicht lieferbarMarke B
Ja lieferbarMarke A und Marke B

​Filter ausprobieren

Wenn man komplexe Filterbedingungen baut, ist es wichtig und nützlich diese zu testen. Hat man es mit großen Datenmengen zu tun, dann dauert die Ausführung von Filtern aber relativ lange und ist mühsam.

Stattdessen kann man Filterbedingungen z.B. mit unserem kostenlosen Tool Transformy testen und dort das Beispiel nutzen.

Beispiel:

Die folgende Filterbedingung

lieferbar! == 'Ja' && ( Hersteller!?trim == 'A' || Hersteller!?trim == 'B')

könnte man testweise in Transformy auch mit <#if><#else> schreiben.

<#if result['A']!?trim == 'Ja' && ( result['B']!?trim == 'Marke A' || result['B']!?trim == 'Marke B' )>Treffer<#else>kein Treffer</#if>

Die beiden Spalten A und B stellen die Quelldaten dar. Auf diese wird per ${result} (sog. Ergebnisspalte) zugriffen. Die Spalte Ergebnis gibt das Wort Treffer aus, wenn die Bedingung zutrifft.
Die Bedingung im Filter-Step nichts anderes als das was innerhalb von <#if> steht.

Um das Beispiel aus dem Screenshot direkt auszuprobieren, bitte hier klickenopen in new window.