Kategoriebaum indizieren zerstört Kategoriebaum in v.4.4.8

Hi,

habe einen Kategoriebaum mit 460 Kategorien. Die Kategorien wurden direkt über den Shop angelegt. Die Zuordnung zu den Artikeln geschieht über eine externe WaWi, die die Tabelle oxobject2category pflegt.

Nun ist es so, dass wenn der “Kategoriebaum neu indiziert” wird in der Tabelle oxcategories die Spalten oxleft und oxright auf 0 gesetzt werden. In dem Popup Fenster passiert auch nichts weiter, kein refresh oder sonstiges.

Unserer WaWi fehlt nun die wichtige Informationen der oxleft und oxright um korrekt zu funktionieren.

Der Shop hingegen zeigt die Kategorien an als wenn nichts wäre, auch im admin können diese normal eingepflegt und editiert werden. Manuelles speichern der Katgorien führt ebenfalls nicht zu einer Neugenerierung der oxright und oxleft.

Es bleibt nur noch übrig ein Backup einzuspielen.

Gibt´s da Erfahrungen, wo könnte ich ansetzen um auf Fehlersuche zu gehen?

Besten Dank vorab:)
René

Sollte nicht so sein, kannst du debuggen in oxcategorylist.php updateCategoryTree und _updateNodes.

Das Problem mit “Kategoriebaum neu indizieren”, habe ich schon bei Tests mit Version 420 bis 448 festgestellt: - es wurde nichts indiziert, alles nur 0.

Das hat mich aber nicht weiter gestört, weil ich die Kategorien mit GUIDs und Indices sowieso offline erzeuge und dann direkt in die DB lade.

Der Shop lief im Test auch ohne Indices, weil diese nur die Zugriffs-Geschwindigkeit beschleunigen sollen. Der Kategorienbaum (tree) selbst wird durch die Verknüpfung der GUIDs (nested sets) in der DB abgebildet.

Bug oder braucht man’s überhaupt?

Habe den Fehler gefunden.

Musste beide Funktionen leicht modifizieren und schon lief´s…
Wie man sieht habe ich nichts anderes getan als:

//$updn = $this->_updateNodes($oxRootId, true, $oxRootId);
$this->_updateNodes($oxRootId, true, $oxRootId);

und alle DB Bezeichner $rs->fields[0] in z.B. $rs->fields[oxid] umzubennenen.

Ohne debuggen wäre ich da niemals draufgekommen - Danke.
Kann mir jemand erklären warum bei mir fields[0] nicht funktioniert?

Da der Code in anderen Versionen z.B. 4.5, vielleicht auch später identisch ist, würde mich interessieren ob dort das Problem ebenfalls auftaucht.

Da die Kategorisierung ohne oxleft und oxright innerhalb des Shops funktioniert, scheint es so als wenn nested sets garnicht verwendet werden, oder?

public function updateCategoryTree($blVerbose = true, $sShopID = null)
    {
        $oDB = oxDb::getDb();
        $sWhere = '1';


        $oDB->execute("update oxcategories set oxleft = 0, oxright = 0 where $sWhere");
        $oDB->execute("update oxcategories set oxleft = 1, oxright = 2 where oxparentid = 'oxrootid' and $sWhere");

        // Get all root categories
        $rs = $oDB->execute("select oxid, oxtitle from oxcategories where oxparentid = 'oxrootid' and $sWhere order by oxsort");
        if ($rs != false && $rs->recordCount() > 0) {
            while (!$rs->EOF) {
                $this->_aUpdateInfo[] = "<b>Processing : ".$rs->fields[oxid]."</b>(".$rs->fields[oxtitle].")<br>";
                if ( $blVerbose ) {
                    echo next( $this->_aUpdateInfo );
                }
                $oxRootId = $rs->fields[oxid];

                //$updn = $this->_updateNodes($oxRootId, true, $oxRootId);
                $this->_updateNodes($oxRootId, true, $oxRootId);
                $rs->moveNext();
            }
        }
    }
protected function _updateNodes($oxRootId, $isroot, $thisRoot)
    {
        $oDB = oxDb::getDb();

        if ($isroot) {
            $thisRoot = $oxRootId;
        }

        // Get sub categories of root categorie
        $rs = $oDB->execute("update oxcategories set oxrootid = ".$oDB->quote($thisRoot)." where oxparentid = ".$oDB->quote($oxRootId));
        $rs = $oDB->execute("select oxid, oxparentid from oxcategories where oxparentid = ".$oDB->quote($oxRootId)." order by oxsort");
        // If there are sub categories
        if ($rs != false && $rs->recordCount() > 0) {
            while (!$rs->EOF) {
                $parentId = $rs->fields[oxparentid];
                $actOxid = $rs->fields[oxid];
                $sActOxidQuoted = $oDB->quote($actOxid);

                // Get the data of the parent category to the current Cat
                $rs3 = $oDB->execute("select oxrootid, oxright from oxcategories where oxid = ".$oDB->quote($parentId));
                while (!$rs3->EOF) {
                    $parentOxRootId = $rs3->fields[oxrootid];
                    $parentRight    = (int)$rs3->fields[oxright];
                    $rs3->moveNext();
                }
                $sParentOxRootIdQuoted = $oDB->quote($parentOxRootId);
                $oDB->execute("update oxcategories set oxleft = oxleft + 2 where oxrootid = $sParentOxRootIdQuoted and oxleft > '$parentRight' and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
                $oDB->execute("update oxcategories set oxright = oxright + 2 where oxrootid = $sParentOxRootIdQuoted and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
                $oDB->execute("update oxcategories set oxleft = $parentRight, oxright = ($parentRight + 1) where oxid = $sActOxidQuoted");
                $this->_updateNodes($actOxid, false, $thisRoot);
                $rs->moveNext();
            }
        }
    }

Wie schon gesagt und jetzt nochmal im Detail:

In oxcategories wird mit den 3 columns OXID, OXPARENTID, OXROOTID der Kategoriebaum gebildet und diese Verbindung bzw. Verschatelung heisst “nested sets”.

Die Indices left right sollen der schnellern Suche dienen und deshalb gehts auch ohne.

Wie sieht denn die Indizierung nach der Codeänderung jetzt aus. Kannst Du prüfen ob die stimmt?

[QUOTE=beme;90017]
Ohne debuggen wäre ich da niemals draufgekommen - Danke.
Kann mir jemand erklären warum bei mir fields[0] nicht funktioniert?
[/QUOTE]
Nö, das solltest du aber evtl. auch debuggen. In oxdb::getdb steht nämlich eigentlich dass wenn kein parameter übergeben wird fetchmode numeric ist, und nicht associative.

[QUOTE=beme;90017]
Da die Kategorisierung ohne oxleft und oxright innerhalb des Shops funktioniert, scheint es so als wenn nested sets garnicht verwendet werden, oder?
[/QUOTE]
Ab und an werden die schon benutzt, bei der SEO-Url-Generierung z.B…

Bin ich jetzt Blöd??

Beim Nested-Sets-Modell wird die Baumstruktur in ineinander verschachtelte Mengen transformiert. Jeder Knoten entspricht einer Teilmenge; jede Teilmenge ist eine Teilmenge aller ihrer Eltern-Mengen.
In einer Datenbank können diese verschachtelten Mengen repräsentiert werden, indem für jede Teilmenge zwei Werte bestimmt werden, die die Grenzen dieser Teilmenge bestimmen. Diese Werte werden oft mit links und rechts bezeichnet. Der Wert links ist immer kleiner als rechts. Beide Werte einer Teilmenge sind größer als der Wert links ihrer Elternmenge und kleiner als deren Wert rechts.

Ohne oxleft und right gibt´s den normalen Baum, ansonsten wird ein nested draus :slight_smile:

Ich kontrollier gerade, ob die Indizierung auch korrekt durchgelaufen ist.

In oxdb::getdb steht nämlich eigentlich dass wenn kein parameter übergeben wird fetchmode numeric ist, und nicht associative.

Yep, das habe ich auch in der odb.php gefunden:

 public static function getDb( $blAssoc = false )
    {
        global $ADODB_FETCH_MODE;

        if ( $blAssoc ) {
            $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
        } else {
            $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
        }

Ich versteh es nicht, Netbeans hat mir bisher auch nicht weitergeholfen.
Hat noch jemand eine Idee, warum adodb hier einen string verlangt?

@Earlybird

Wie sieht denn die Indizierung nach der Codeänderung jetzt aus. Kannst Du prüfen ob die stimmt?

Hab´s getestet und funktioniert nun 100% :slight_smile:

Gratulation zum Erfolg.

Dann ist das doch ein Bug in OXID gewesen und vielleicht immer noch in der aktuellen Version vorhanden?

Zu Deiner voreherigen Feststellung (Wiki) kann ich sagen, dass die Begriffe und Anwendungstechniken nicht immer einheitlich verwendet werden:

The nested set model is a particular technique for representing nested sets (also known as trees or hierarchies) in relational databases. The term was apparently introduced by Joe Celko; others describe the same technique without naming it [1] or using different terms. [2]

OXID verwendet beides, das Parent-Child Model und Nested Sets, in einer eigenen Kombanatation zusammen:

Vom Prinzip her kann mit jedem dieser Modell unabhängig voeinader ein kompletter Kategoriebaum erstellt werden und es gibt noch andere Möglichkeiten.

Das Parent-Model allein wäre bei Queries aber langsamer und reine Nested Sets allein wären zu komplex und langsamer wenn eine Katagerie geändert oder entfernt wird und der Kategoriebaum wieder neu aufgebaut werden muss - natürlich nur bei entsprecheder Grösse.

Siehe dazu auch folgenden Link:
http://www.evanpetersen.com/item/nested-sets.html

War mal interessant darüber zu diskutieren und Haupsache es läuft jetzt rund.

Machs gut!

[QUOTE=Earlybird;90029]Wie schon gesagt und jetzt nochmal im Detail:

In oxcategories wird mit den 3 columns OXID, OXPARENTID, OXROOTID der Kategoriebaum gebildet und diese Verbindung bzw. Verschatelung heisst “nested sets”.

Die Indices left right sollen der schnellern Suche dienen und deshalb gehts auch ohne.[/QUOTE]

Mag sein, dass die Speicherung eines Baumes nach dem Nested-Sets-Modell manchmal auch anders benannt wird, aber die Speicherung mit Parent-IDs und Sortierfeldern wird niemals als Nested-Sets-Modell bezeichnet.