Transformationsbeispiele

Sie können Ihre CloudEvents-Daten transformieren, indem Sie Transformationsausdrücke mit CEL schreiben. Weitere Informationen finden Sie unter Empfangene Ereignisse transformieren.

Im Folgenden finden Sie einige gängige Anwendungsfälle und Beispiele, die zeigen, wie Sie CEL-Ausdrücke schreiben, um Ihre Ereignisdaten zu transformieren.

Standardanwendungsfälle

Im Folgenden sind einige Standardanwendungsfälle für die Transformation von Ereignisdaten aufgeführt.

Datennormalisierung

Sie müssen eine verschachtelte Datenstruktur in Ihrer Ereignisnachricht flachstellen, damit sie von einem Downstream-Dienst leichter verarbeitet werden kann.

Szenario:

Angenommen, Sie haben die folgenden CloudEvents-Daten:

{
  "data": {
    "orderId": "12345",
    "customer": {
      "firstName": "Alex",
      "lastName": "Taylor",
      "address": {
        "street": "1800 Amphibious Blvd.",
        "city": "Mountain View"
      }
    }
  }
}

Sie möchten einen CEL-Ausdruck schreiben, der zu der folgenden Ausgabe führt:

{
  "data": {
    "orderId": "12345",
    "customerFirstName": "Alex",
    "customerLastName": "Taylor",
    "customerStreet": "1800 Amphibious Blvd.",
    "customerCity": "Mountain View"
  }
}
Lösung 1:

Formatieren Sie die Ausgabedaten manuell. So können Sie die Feldnamen auflisten und nur die Elemente auswählen, die in der Ausgabe benötigt werden. Das ist ein sinnvoller Ansatz, wenn die Eingabe vorhersehbar ist und die Anzahl der Felder gering ist. Mit der Funktion setField wird ein Feld des Ereignisses mit einem bestimmten Schlüssel hinzugefügt oder ersetzt. Beispiel:

message.setField("data",
{
  "orderId": message.data.orderId,
  "customerFirstName": message.data.customer.firstName,
  "customerLastName": message.data.customer.lastName,
  "customerStreet": message.data.customer.address.street,
  "customerCity": message.data.customer.address.city,
})
Lösung 2:

Verwenden Sie eine Funktion in Ihrem Ausdruck. Mit der Funktion setField wird ein Feld des Ereignisses mit einem bestimmten Schlüssel hinzugefügt oder ersetzt. Die Funktion denormalize bricht tiefe Strukturen in eine Liste von Schlüssel/Wert-Paaren auf. Feldnamen werden durch einen Punkt (.) voneinander getrennt, um die Strukturhierarchie zu segmentieren. Beispiel:

message.setField("data", message.data.denormalize())

Das führt zur folgenden Ausgabe, die sich geringfügig von der erwarteten Nutzlast unterscheidet. Zu den Vorteilen gehören jedoch ein kürzerer CEL-Ausdruck, der auf jede Eingabe angewendet werden kann und automatisch eine beliebige Anzahl eingehender Felder enthält.

{
  "data": {
    "orderId": "12345",
    "customer.firstName": "Alex",
    "customer.lastName": "Taylor",
    "customer.address.street": "1800 Amphibious Blvd.",
    "customer.address.city": "Mountain View"
  }
}

Datenmaskierung

Sie müssen sensible Daten in einer Ereignisnutzlast maskieren, bevor sie an eine weniger sichere Umgebung gesendet werden.

Szenario:

Angenommen, Sie haben die folgenden CloudEvents-Daten:

{
  "data": {
    "userId": "user123",
    "email": "alex@example.com",
    "creditCardNumber": "1234-5678-9012-3456"
  }
}

Sie möchten einen CEL-Ausdruck schreiben, der zu der folgenden Ausgabe führt:

{
  "data": {
    "userId": "user123",
    "email": "a***@example.com",
    "creditCardNumber": "xxxx-xxxx-xxxx-3456"
  }
}
Lösung:

Verwenden Sie einen Ausdruck, um vertrauliche Informationen wie die E-Mail-Adresse und die Kreditkartennummer zu maskieren. Mit der Funktion setField wird ein Feld des Ereignisses mit einem bestimmten Schlüssel hinzugefügt oder ersetzt. Die reguläre Ausdrucksfunktion extract folgt der RE2-Syntax. Beispiel:

message
      .setField("data.email",
          re.extract(message.data.email,
                    "(^.).*@(.*)",
                    "\\1***@\\2"))

      .setField("data.creditCardNumber",
          re.extract(message.data.creditCardNumber,
                    "(\\d{4})\\D*$",
                    "xxxx-xxxx-xxxx-\\1"))

Datenentfernung

Sie müssen bestimmte Felder aus einer Ereignisnutzlast entfernen, wenn bestimmte Bedingungen erfüllt sind.

Szenario:

Angenommen, Sie haben die folgenden CloudEvents-Daten:

{
  "data": {
    "orderId": "12345",
    "customerType": "gold",
    "discountCode": "VIP"
  }
}

Sie möchten einen CEL-Ausdruck schreiben, der zu der folgenden Ausgabe führt:

{
  {
  "orderId": "12345",
  "customerType": "gold"
  }
}
Lösung:

Verwenden Sie einen Ausdruck, der das Feld discountCode entfernt, wenn customerType „gold“ ist. Mit der Funktion removeFields werden bestimmte Felder aus einem Ereignis entfernt. Beispiel:

message.data.customerType == "gold" ?
      message.removeFields(["data.discountCode"]) :
      message

Datenkonvertierung

Sie müssen Daten von einem Format oder Typ in einen anderen konvertieren.

Szenario:

Angenommen, Sie haben die folgenden CloudEvents-Daten:

{
  "data": {
    "orderDate": "2024-10-31T12:00:00Z",
    "totalAmount": "1500"
  }
}

Sie möchten einen CEL-Ausdruck schreiben, der zu der folgenden Ausgabe führt:

{
  "data": {
    "orderDate": 1704086400,
    "totalAmount": 1500.00
  }
}
Lösung:

Verwenden Sie einen Ausdruck, der orderDate in einen UNIX-Zeitstempel und den totalAmount-Typ von string in double (Gleitkommazahl) konvertiert. Mit der Funktion setField wird ein Feld des Ereignisses mit einem bestimmten Schlüssel hinzugefügt oder ersetzt. Sie können Funktionen zur Stringmanipulation verwenden, um die Stringergebnisse zu konvertieren. Beispiel:

message
      .setField("data.orderDate", int(timestamp(message.data.orderDate)))
      .setField("data.totalAmount", double(message.data.totalAmount))

Bedingtes Routing

Sie müssen Ereignisse basierend auf den Ereignisdaten an verschiedene Ziele weiterleiten.

Szenario:

Angenommen, Sie haben die folgenden CloudEvents-Daten:

{
  "data": {
    "eventType": "order.created",
    "orderValue": 200
  }
}

Sie möchten einen CEL-Ausdruck schreiben, der zu der folgenden Ausgabe führt:

{
  "data": {
    "eventType": "order.created",
    "orderValue": 200,
    "routingKey": "highValue"
  }
}
Lösung:

Verwenden Sie einen Ausdruck, der ein routingKey-Feld mit dem Wert „highValue“ hinzufügt, wenn orderValue größer als 100 ist, andernfalls "normal". Mit dem Feld routingKey kann der Routingpfad ermittelt werden. Mit der Funktion setField wird ein Feld des Ereignisses mit einem bestimmten Schlüssel hinzugefügt oder ersetzt. Beispiel:

message.data.orderValue > 100 ?
      message.setField("data.routingKey", "highValue") :
      message.setField("data.routingKey", "normal")

Umgang mit Standardwerten

Bestimmte Felder in der Ereignisnutzlast müssen Standardwerte haben, falls sie nicht vorhanden sind.

Szenario:

Angenommen, Sie haben die folgenden CloudEvents-Daten:

{
  "data": {
    "itemName": "Product A"
  }
}

Sie möchten einen CEL-Ausdruck schreiben, der zu der folgenden Ausgabe führt:

{
  "data": {
    "itemName": "Product A",
    "quantity": 1
  }
}
Lösung:

Verwenden Sie einen Ausdruck, der ein quantity-Feld mit dem Standardwert 1 hinzufügt, wenn das Feld noch nicht vorhanden ist. Mit dem Makro has wird geprüft, ob ein Feld verfügbar ist. Mit der Funktion setField wird ein Feld des Ereignisses mit einem bestimmten Schlüssel hinzugefügt oder ersetzt. Beispiel:

has(message.data.quantity)  ?
    message :
    message.setField("data.quantity", 1)

String-Manipulation

Sie müssen Teile eines Stringfelds in den Ereignisdaten extrahieren oder ändern.

Szenario:

Angenommen, Sie haben die folgenden CloudEvents-Daten:

{
  "data": {
    "customerEmail": "alex@example.com"
  }
}

Sie möchten einen CEL-Ausdruck schreiben, der zu der folgenden Ausgabe führt:

{
  "data": {
    "customerEmail": "alex@example.com",
    "emailDomain": "example.com"
  }
}
Lösung:

Verwenden Sie einen Ausdruck, mit dem der Domainname („beispiel.de“) aus dem Feld customerEmail extrahiert und in einem neuen Feld emailDomain gespeichert wird. Mit der Funktion setField wird ein Feld des Ereignisses mit einem bestimmten Schlüssel hinzugefügt oder ersetzt. Die reguläre Ausdrucksfunktion extract folgt der RE2-Syntax. Beispiel:

message
  .setField("data.emailDomain",
re.extract(message.data.customerEmail, "(^.*@)(.*)", "\\2"))

Listen- und Zuordnungsvorgänge

Sie müssen in den Ereignisdaten mit Listen oder Karten arbeiten.

Szenario:

Angenommen, Sie haben die folgenden CloudEvents-Daten:

{
  "data": {
    "productIds": [
      "product123",
      "product456"
    ]
  }
}

Sie möchten einen CEL-Ausdruck schreiben, der zu der folgenden Ausgabe führt:

{
  "data": {
    "productIds": [
      "product123",
      "product456"
    ],
    "productFound": true
  }
}
Lösung:

Verwenden Sie einen Ausdruck, der prüft, ob „Produkt456“ in der Liste productIds vorhanden ist, und das Ergebnis (true oder false) in einem neuen productFound-Feld speichert. Mit der Funktion setField wird ein Feld des Ereignisses mit einem bestimmten Schlüssel hinzugefügt oder ersetzt. Mit dem Makro exists wird geprüft, ob ein Prädikat für alle Elemente einer Liste gilt, und die Ergebnisse mit dem Operator „or“ kombiniert. Beispiel:

message.setField("data.productFound",
        message.data.productIds.exists(id, id == "product123"))

Fehlerbehandlung

Sie müssen mit potenziellen Fehlern oder unerwarteten Daten in der Ereignisnutzlast angemessen umgehen.

Szenario:

Angenommen, Sie haben die folgenden CloudEvents-Daten:

{
  "data": {
    "quantity": "abc"
  }
}

Sie möchten einen CEL-Ausdruck schreiben, der zu der folgenden Ausgabe führt:

{
  "data": {
    "quantity": 0,
    "error": "Invalid quantity"
  }
}
Lösung:

Verwenden Sie einen Ausdruck, mit dem versucht wird, das Feld quantity in eine Ganzzahl umzuwandeln. Wenn die Conversion fehlschlägt, setzen Sie das Feld quantity auf 0 und fügen Sie ein neues Feld error mit dem Wert „Ungültige Stückzahl“ hinzu.

  • Mit dem Makro has wird geprüft, ob ein Feld verfügbar ist.
  • Die Funktion type gibt den Typ eines Werts zurück.
  • Die reguläre Ausdrucksfunktion matches folgt der RE2-Syntax.
  • Mit der Funktion setField wird ein Feld des Ereignisses mit einem bestimmten Schlüssel hinzugefügt oder ersetzt.

Beispiel:

// Check if data.quantity exists
has(message.data.quantity) &&
// Check if data.quantity is a string
type(message.data.quantity) == string &&
// Check if string consists of digits
message.data.quantity.matches(r'^-?[0-9]+$') ?
  // If data.quantity is valid, use message
  message :
  // If data.quantity is invalid, set to 0 and generate error
  message
    .setField("data.quantity", 0)
    .setField("data.error", "Invalid quantity")

Komplexe Anwendungsfälle

Im Folgenden finden Sie einige komplexe Anwendungsfälle für die Transformation von Ereignisdaten.

Datenumwandlung

Sie müssen mehrere Transformationen auf verschachtelte Ereignisdaten ausführen.

Szenario:

Angenommen, Sie haben die folgenden CloudEvents-Daten:

{
  "data": {
    "orderId": "12345",
    "customer": {
      "firstName": "Alex",
      "lastName": "Taylor",
      "email": "alex@example.com",
      "address": {
        "street": "1800 Amphibious Blvd.",
        "city": "Mountain View",
        "state": "CA"
      }
    },
    "items": [
      {
        "itemId": "item1",
        "price": 10.00,
        "quantity": 2
      },
      {
        "itemId": "item2",
        "price": 5.00,
        "quantity": 1
      }
    ]
  }
}

Sie möchten einen CEL-Ausdruck schreiben, der zu der folgenden Ausgabe führt:

{
  "data": {
    "orderId": "12345",
    "customer.firstName": "Alex",
    "customer.lastName": "Taylor",
    "customer.email": "a***@example.com",
    "customer.address.city": "Mountain View",
    "customer.address.state": "CA"
  }
}
Lösung:

Verwenden Sie einen Ausdruck, mit dem die Stadt und der Bundesstaat aus der Adresse extrahiert und die E-Mail-Adresse maskiert werden.

  • Mit der Funktion setField wird ein Feld des Ereignisses mit einem bestimmten Schlüssel hinzugefügt oder ersetzt.
  • Die Funktion toMap wandelt eine CEL-Liste mit CEL-Maps in eine einzelne CEL-Map um.
  • Die reguläre Ausdrucksfunktion extract folgt der RE2-Syntax.
  • Mit der Funktion removeFields werden bestimmte Felder aus einem Ereignis entfernt.
  • Die Funktion denormalize wandelt tiefe Strukturen in eine Liste von Schlüssel/Wert-Paaren um. Feldnamen werden durch einen Punkt (.) voneinander getrennt, um die Strukturhierarchie zu segmentieren.

Beispiel:

message
.setField("data",
  message.data.setField("customer.address",
    message.data.customer.address.map(key, key == "city" || key == "state",
          { key: message.data.customer.address[key] }).toMap())
  .setField("customer.email",
        re.extract(message.data.customer.email, "(^..?).*@(.*)", "\\1***@\\2"))
  .removeFields(["items"])
  .denormalize()
)

Datenformatierung und -weiterleitung

Sie müssen Ereignisdaten formatieren, Produktinformationen hinzufügen und dann die Ereignisnachricht weiterleiten.

Szenario:

Angenommen, Sie haben die folgenden CloudEvents-Daten:

{
  "data": {
    "productId": "p123",
    "productName": "Example Product",
    "category": "electronics"
  }
}

Sie möchten einen CEL-Ausdruck schreiben, der zu der folgenden Ausgabe führt:

{
  "data": {
    "productId": "electronics-p123",
    "productName": "EXAMPLE PRODUCT",
    "category": "electronics",
    "routingKey": "electronics"
  }
}
Lösung:

Verwenden Sie einen Ausdruck, der den Produktnamen in Großbuchstaben formatiert, der Produkt-ID basierend auf ihrer Kategorie ein Präfix hinzufügt und einen Routingschlüssel für die nachfolgende Verarbeitung enthält. Mit der Funktion setField wird ein Feld des Ereignisses mit einem bestimmten Schlüssel hinzugefügt oder ersetzt. Die Funktion upperAscii gibt einen String zurück, in dem alle ASCII-Zeichen in die entsprechenden Großbuchstaben umgewandelt sind. Beispiel:

message
.setField("data.productId",
message.data.category + "-" + message.data.productId)
.setField("data.productName", message.data.productName.upperAscii())
.setField("data.routingKey", message.data.category)