Datensätze vergleichen und ändern

Hallo,

und zwar hole ich mir über einen API-Call alle verfügbaren Datensätze. Ich speichere sie von XMLReader in „Data Management“. Da es mehrere API-Calls gibt, soll dort alle Daten richtig zusammen gepuzzelt werden, damit sie dann von dort in das Shopware-System übertragen werden können.

Nun sind über den einen API-Call die Datensatznummern so gestrickt, dass der ein oder andere Datensatz ein Unterdatensatz ist.

Beispiel:

1234598
123459801
123459802

Der zweite und dritte Datensatz gehören zu 1234598.

Nun hatte ich überlegt, dass ich einen weiteren API-Call mache, nachdem alle anderen API-Calls durch sind, und diesen mit dem Data Management vergleiche und die entsprechenden Datensatznummern vergleiche und per freemarker verarbeite. Aber sehe nicht die Möglichkeit, dass in einem Step hierfür zu vergleichen bzw. dann auch ändern zu können. Auch das Data Management miteinander zu vergleichen/ändern, ist nicht möglich.

Mir fehlt hier ein kleiner Anstoß dazu, wie ich eine Vergleichmöglichkeit habe, um dann in einem Feld „parentNumber“ die Haupt-Datensatznummer einzutragen.

Kann jemand helfen?

Beste Grüße
Daniel

Hallo Daniel,

leider wird für mich nicht hundert Prozentig klar wo hier die Problematik ist.
Mein erster Ansatz wäre hier die Relation über die ID aufzubauen, da hier scheinbar die Parent ID Teil der ID ist.
Ansonsten müsstest du einmal eine (bereinigte) Response aus deinem API Call posten zusammen mit dem Parsing Script aus dem XML Reader .
Dann könnte man zusammen schauen welche Daten da sind und welche nicht.

VG
Stefan

Mir geht es darum, dass ich immer nur eine Datensatznummer in der Schleife habe, worauf ich in dem Moment zugreifen kann. Ich muss sie aber über alle Datensätze einmal vergleichen können. Und dieser Ansatz fehlt mir, zu sagen, mache eine Schleife über alle Datensätze und vergleiche sie mit dem jetzt gerade vorhandenen Datensatz. Sprich, quasi jeden einzelnen Datensatz gegen alle Datensätze abgleichen.

Ich habe einen Lösungsansatz und die Lösung gefunden. Falls jemand es auch mal brauch, hier meine Lösung:

1.Step: API-Call
2. XMLReader

<#assign row = target.addRow()>

<#list xml["ROOT"]["ARTIKEL"] as artikel1>
  <#assign row = target.addRow()>
  ${addColumns(row, artikel1)}

  <#assign artikelnr1 = artikel1["ARTIKELNR"]>
  <#assign artikel1_index = artikel1?index>
  <#list xml["ROOT"]["ARTIKEL"] as artikel2>
    <#if artikel1_index < artikel2?index>
      <#assign artikelnr2 = artikel2["ARTIKELNR"]>
        <#if artikelnr2?starts_with(artikelnr1) && artikelnr2?length gt artikelnr1?length>
          ${row.addCol("parentProductNumber", artikelnr2)}
        </#if>
        
    </#if>
  </#list>
</#list>
  1. ich speichere mir das dann in dem jeweiligen Feld parentProductNumber im Data Management.

Bei ca. 30000 Datensätze führt das nun zum Fehler von Synesty, weil es zu viele Daten sind. :frowning:

Hi @Lemm

im Moment iterierst du pro Artikel einmal durch die komplette XML Datei.
Bei 30.000 Datensätzen kommst du also auf 900.000.000 Iterationen.

Dass dann Synesty in die Knie geht ist nicht unerwartet.

Unter der Voraussetzung, dass die Länge aller Parent (7) und Children (9) IDs immer gleich ist, würde ich folgenden Weg vorschlagen:

  1. Aus dem Parsing Template entfernst du den Teil mit der Parent Child Relation
  2. Du lädst dein geparstes XML ohne Parent Child Relation in deinen Datastore
  3. Anschließend nimmst du das selbe geparste XML und setzt einen Substring auf die Artikel ID um somit auf die Parent ID zu kommen.
  4. Du machst mit der „gerateten“ Parent ID einen Querverweis auf den Datastore.
  5. Wenn du einen Treffer hast dann ist das deine wirkliche Parent ID, die du dann nochmal im Datastore nachpflegen kannst.

Die Struktur des Flows würde dann in etwa so aussehen.

Viele Grüße
Stefan

Ich hatte gestern Abend noch einen anderen Ansatz gefunden.

<#assign row = target.addRow()>
<#assign artikelnr1_list = ["1904000501", "1904000502"]>

<#list artikelnr1_list as artikelnr1_value>
  <#assign row = target.addRow()>
  ${row.addCol("productNumber", artikelnr1_value)}

  <#assign parentProductNumber = "">

  <#list xml["ROOT"]["ARTIKEL"] as artikel2>
    <#assign artikelnr2 = artikel2["ARTIKELNR"]>

    <#assign startsWithCondition = artikelnr1_value?starts_with(artikelnr2)>
    <#assign lengthCondition = artikelnr1_value?length gt artikelnr2?length>
    
    <#if startsWithCondition && lengthCondition>
      <#assign parentProductNumber = artikelnr2>
      <#break>
    </#if>
  </#list>

  ${row.addCol("parentProductNumber", parentProductNumber)}
</#list>

Das funktioniert auch wunderbar. Nun sind aber die zwei Artikelnummern in Zeile 2 von mir statisch angelegt.

Wie kommen die Artikelnummern bei mir dynamisch? Ich mache jeden Tag ein API-Call, wo ich nur die Artikel erhalte, die am letzten Tag geändert wurden. Wenn ich in Zeile 2 an diese Artikelnummern komme, dann wäre es gelöst. Nur fehlt mir auch hier der Weg (ähnlich wie im Nachbarthread), der Weg über die Synesty-Einstellung, wie ich damit umgehen kann, wenn zwei API-Calls mache.

Aktuelle Flow:
Screenshot 2024-08-22 091101

Im XMLReader steht der Code drin, den ich hier aufgeführt habe. Aus API-Call kommen die 30.000 Artikel. Nur wo und wie oder an welcher Stelle kann ich den API-Call hinzufügen, wo ich mir nur die Daten des letzten Tages ziehe? Ich hatte schon überlegt, ob ich die Artikelnr. in die festen Variablen schreiben lasse, um dann in Zeile 2 auf sie zugreifen zu können. Aber hierzu habe ich keine Steps gefunden. Zwei API-Calls hintereinander habe ich auch keine Lösung gefunden.

@sHelme Danke für deine Mühe. Leider komme ich mit deiner Ausführung nicht zurecht, bzw. erhalte ich hier nicht das gewünschte Ergebnis. Ich übersetze deine Ausführung, wie ich sie umgesetzt habe. Ggf. habe ich ein Fehler gemacht.

  1. Ich habe aus einem API-Call die Daten in den Datastore geschrieben.
  2. XML-Reader habe ich auf folgendes gekürzt:
<#assign row = target.addRow()>

<#list xml["ROOT"]["ARTIKEL"] as artikel1>
  <#assign row = target.addRow()>
  ${addColumns(row, artikel1)}
</#list>
  1. Step3 ist dann der „Mapper“. Hier habe ich versucht, einen Substring zu machen.


Das ist nun die Spalte, wo ich die parentID ausgeben lassen möchte. In dem Screenshot unter „Rückgabe bei Treffer“ wollte ich nun das von dir beschriebene Substring. umsetzen, jedoch besteht die Möglichkeit dort nicht. Daher habe ich über Skript versucht. Aber auch hier ohne Erfolg, aber auch, weil ich nicht verstehe, was anstelle von „wert2“ hin muss.

Fehlermeldung des Steps:

error in function Scripting: Template parsing error (Root Causes: ParseException: Syntax error in template „ScriptCol parentProductNumber“ in line 1, column 6: You can’t use ${…} (an interpolation) here as you are already in FreeMarker-expression-mode. Thus, instead of ${myExpression}, just write myExpression. (${…} is only used where otherwise static text is expected, i.e., outside FreeMarker tags and interpolations, or inside string literals.))

Hi @Lemm
du bist schon auf dem richtigem Weg, es fehlt aber noch etwas.
Folgende Punkte:

  1. Du musst in deinem Identifier nach dem Substring suchen. Du suchst ja nicht nach dem eigenen Eintrag der ArtikelNr, sondern nach dem erwarteten Parent.
  2. Du hast kein Rückgabefeld bei Treffer angegeben. Den brauchst du, da du ansonsten dein Querverweis nicht funktioniert.
  3. In deinem Script benutzt du innerhalb der If-Condition ein ${…}. Das musst du nicht, es reicht bereits die Variable selbst.
  4. In deinem Script beziehst du dich nicht auf den momentanen Wert. Das wäre an der Stelle _currentValue

Hier mein Tipp an dich um das Debuggen leichter zu machen:
Mach nicht alles in einer Spalte sondern teile deine Schritte auf mehrere Spalten auf. Das hilft beim Debuggen ungemein.
Heißt also dann
Spalte 1: Substring nehmen um den erwarteten Parent Identifier heraus zu finden. (Geht auch bei Textfunktion)
Beispiel:

Spalte 2:
Querverweis auf deinen Datastore mit dem erwarteten Parent Identifier

Spalte 3:
Prüfung ob Querverweise geklappt hat oder nicht

1 „Gefällt mir“

@sHelme
Es funktioniert, und danke dir damit sehr. Hätte ich ohne deine Hilfe nicht hinbekommen. Danke!!

Nun wird zwar auch im „parentProductNumber“ etwas eingetragen, wenn die „productNumber“ die Gleiche ist, aber das ist das kleinere Übel.

Kein Problem :+1:

Vor deinem zweiten Datastore Writer kannst du einen Filter Step setzen um nur dort eine Parent Nummer zu schreiben wo Diese ungleich der momentanen Artikelnummer ist.

Viele Grüße
Stefan

@sHelme
Ich habe nur einen. :slight_smile: Klappt davor leider nicht, weil die Daten da nicht ankommen.

Werde ich vermutlich nochmal eine SearchDatabase, Filter und DatastoreWriter machen müssen. Ich denke, damit sollte es klappen. Probiere ich später.