Suche erweitern objectType AdditionalData

  • Guten Abend zusammen,

    ich versuche derzeit die hauseigene Suchfunktion zu erweitern und habe bereits mal ein objectType über das objectType-PiP angelegt für die Definition com.woltlab.wcf.searchableObjectType. Ich wundere mich nur etwas, dass bei den zwei bestehenden objectTypes (für die Suche in Seiten und Artikel) in der Tabelle wcfN_object_type die Spalte additionalData verfügbar ist. Für die Artikel-Suche bspw. ein serialisiertes Array a:1:{s:11:"searchindex";s:25:"wcf1_article_search_index";}. Was hat das für einen Hintergrund? Muss ich dies für die Erweiterung der Suche berücksichtigen im eigenen objectType?

    Im gleichen Zuge auch noch die Frage: Ich habe über das Page-PiP eine eigene Seite angelegt (bspw. Cars). Diese wird mir im ACP unter "Inhalt -> Seiten" auch angezeigt. Allerdings lässt sich diese Seite nicht finden über die Suchfunktion wenn "Seiten" angeklickt ist. Weshalb ist das so?

    Info: Alle oben genannten Ausführungen basieren auf einer frischen WSC Installation. Sollte es noch irgendwie einfacher sein die Suche zu erweitern, bin ich für Tipps natürlich dankbar. :)

    Grüße,

    JAY

    • Offizieller Beitrag

    Hallo,

    "Seiten" meint nur CMS-Seiten und keine Inhalte vom Typ vom Typ "System", weil diese dynamischer Natur sind. additionalData kann verwendet werden, um zusätzliche Inhalte in die Suche mit aufzunehmen, die nicht im eigentlichen Textinhalt vorkommen. Bei der Filebase hinterlegen wir dort beispielsweise den Teaser.

  • Danke für die Info. Jetzt macht es etwas mehr Sinn.. ^^

    Die Suche will aber derzeit noch nicht so wirklich wie ich will. Kann mir da jemand auf die Sprünge helfen?

    Ich habe grundlegend eine Car-Klasse bei der z. B. der Title in der Datenbank durchsucht werden soll. Mehr soll erstmal nicht passieren. Gibt es irgendetwas spezielles was ich beachten muss?

    Ich habe ein objectType angelegt:

    Code
        <import>
            <type>
                <name>de.itsmejay.wcf.car</name>
                <classname>wcf\system\search\CarSearch</classname>
                <definitionname>com.woltlab.wcf.searchableObjectType</definitionname>
            </type>
        </import>

    Anschließend wird in der Suche auch direkt der neue objectType angezeigt. Über die Klasse wcf\system\search\CarSearch pflege ich folgende Methoden. Ich habe bewusst z. B. die getJoins() Methode weggelassen, da auf keine andere Tabelle gejoint werden muss.

    PHP-Code

    Wenn ich nun ein Car anlege mit dem carName 'Volkswagen' und dies suchen will, findet er dies derzeit noch nicht. Er greift aber zumindest auf die Klasse zurück, weil bei fehlerhaften Tabellenname ein Error geschmissen wird bei der Suche.

    Vergesse ich irgendwelche Methoden aus Interfaces o.Ä? Ich mach doch eigentlich nicht anders als bei der PageSearch. :/:/

    Einmal editiert, zuletzt von itsmeJAY (1. Februar 2021 um 19:27)

  • Dir fehlt die Sache rund um den SearchIndexManager sowie ggf. der RebuildDataWorker, um den Suchindex für deine Objekte erstmal anzulegen. Vorher weiß das System nichts von deinen Datensätzen.

  • Dir fehlt die Sache rund um den SearchIndexManager sowie ggf. der RebuildDataWorker

    Danke für den Tipp. Ich habe mir das mal angeschaut, aber macht das der SearchIndexManager nicht automatisch wenn ich den objectType für die entsprechende Definition installiere / installiert habe?

    Code
        protected function init() {
            // get available object types
            $this->availableObjectTypes = ObjectTypeCache::getInstance()->getObjectTypes('com.woltlab.wcf.searchableObjectType');
        }

    Der müsste somit doch auch meinen objectType haben und über den objectType somit die Klasse, welche die Objekte holt? Was genau übersehe ich oder gehe ich da komplett falsch ran? :/

  • Dir fehlt die Sache rund um den SearchIndexManager sowie ggf. der RebuildDataWorker, um den Suchindex für deine Objekte erstmal anzulegen. Vorher weiß das System nichts von deinen Datensätzen.

    Ich habe mich nun noch etwas genauer in den Code reingelesen. Ich sehe jetzt, dass über den SearchIndexManager  u.a die Tabelle wcf1_page_search_index nach erfolgreicher Erstellung einer Seite (Page) gefüllt wird. Das müsste ich dann auch in der Action meiner Klasse erledigen, das sollte erst einmal kein Problem darstellen.

    Woraus ich aber immer noch nicht schlau werde ist folgendes. Ich hoffe mir kann da jemand auf die Sprünge helfen.

    1) Muss ich die Tabelle wcf1_car_search_index über die install.sql anlegen beim Paket installieren? Ich komme etwas mit den bereits existierenden additionalData-Werten durcheinander. Wofür wird bspw. a:1:{s:11:"searchindex";s:22:"wcf1_page_search_index";} im ObjectType com.woltlab.wcf.page verwendet? Wird dadurch ggf. die Tabelle automatisch angelegt? Die Werte stehen sicherlich nicht ohne Grund drin, ich kann die Werte in der entsprechenden objectType-Klasse wcf\system\search\PageSearch aber nicht wiederfinden.

    2) Wie bekomme ich über einen RebuildDataWorker die bereits gepflegten Objekte in den Search-Index? Den Worker anlegen scheint erst einmal nicht das Problem, nur wann und wie wird er ausgeführt?

    3) Wofür ist die Klasse wcf\system\search\PageSearch zuständig wenn doch bereits alle Objekte im Search-Index verfügbar sind? Die Klasse scheint auf die page_content Tabelle zurückzugreifen.

    Grüße und schönen Abend

    JAY

    • Offizieller Beitrag

    1) Muss ich die Tabelle wcf1_car_search_index über die install.sql anlegen beim Paket installieren?

    Nein, auf gar keinen Fall ;) Die Tabelle wird automatisch erstellt und verwaltet, wenn du aber keinen Namen angibst, wird der automatisch generiert. Den Namen legst du über ein zusätzliches Element in der objectType.xml fest: https://github.com/WoltLab/com.wo…jectType.xml#L8

    Den Worker anlegen scheint erst einmal nicht das Problem, nur wann und wie wird er ausgeführt?

    Von alleine überhaupt nicht, die Worker landen, wenn man sie korrekt registriert hat, im ACP unter "Wartung > Anzeigen aktualisieren": https://github.com/WoltLab/com.wo…ype.xml#L81-L93

    3) Wofür ist die Klasse wcf\system\search\PageSearch zuständig wenn doch bereits alle Objekte im Search-Index verfügbar sind?

    Dies steuert die Logik für die Suchmaske bzw. die Anzeige der Ergebnisse, siehe https://github.com/WoltLab/com.wo…earch.class.php

  • Nein, auf gar keinen Fall ;) Die Tabelle wird automatisch erstellt und verwaltet, wenn du aber keinen Namen angibst, wird der automatisch generiert. Den Namen legst du über ein zusätzliches Element in der objectType.xml fest:

    Danke für deine Antwort. ;) Irgendwie schafft Du es, dass es sofort klar wird.

    Die Tabelle ist bei mir aber nicht angelegt wurden, obwohl ich dies über das richtige PiP installiert habe. Oder wird die Tabelle erst angelegt, sobald der erste Eintrag zu dem objectType über den SearchIndexManager erstellt wird?

    So, jetzt aber bis morgen. Bleibt gesund allesamt.

    JAY

    • Offizieller Beitrag

    Die Tabelle ist bei mir aber nicht angelegt wurden, obwohl ich dies über das richtige PiP installiert habe. Oder wird die Tabelle erst angelegt, sobald der erste Eintrag zu dem objectType über den SearchIndexManager erstellt wird?

    Dies passiert automatisch am Ende der Paketinstallation, bitte kontrolliere, ob der Objekt-Typ der korrekten Definition zugeordnet ist und die Schreibweise des Tags für den Namen passt.

  • und die Schreibweise des Tags für den Namen passt.

    Ist es nicht egal wie mein objectType heißt solange die Definition stimmt? Oder was genau meinst du mit "Tags"? Ich installiere derzeit noch wie folgt:

    Code
        <import>
            <type>
                <name>de.itsmejay.wcf.car</name>
                <classname>wcf\system\search\CarSearch</classname>
                <definitionname>com.woltlab.wcf.searchableObjectType</definitionname>
            </type>
        </import>
  • Bitte erschlagt mich nicht gleich, aber nachdem das mit den objectTypes nun alles, wie von Alexander Ebert beschrieben, geklappt hat, habe ich eine neue Klasse SearchResultCar angelegt welche von DatabaseObjectDecorator erbt (genau so, wie es die SearchResultPageContent derzeit macht). Als $baseClass ist dieCar::class gesetzt. Die Car-Klasse implementiert ILinkableObject. Der SearchIndex in der Datenbank ist auch gefüllt, dennoch bekomme ich bei jedem Aufruf bzw. bei jeder Suche welche eigentlich ein Treffer sein sollte folgende Fehlermeldung:

    Code
    Error Message:
    
    'wcf\data\car\SearchResultCar' can't decorate objects of class 'wcf\data\car\SearchResultCar'

    Ich würde die Fehlermeldung ja verstehen, aber es ist doch die richtige $baseClass gesetzt.

    Jemand den Fehler schonmal gehabt? Was übersehe ich denn nun schon wieder? ... ?(

  • Wie sieht denn CarSearch::cacheObjects() mittlerweile aus?

    Code
    public function cacheObjects(array $objectIDs, array $additionalData = null) {
        $list = new SearchResultCarList();
        $list->setObjectIDs($objectIDs);
        $list->readObjects();
        foreach ($list->getObjects() as $content) {
            $this->messageCache[$content->carID] = $content;
        }
    }

    Die SearchResultCarList Klasse existiert natürlich und hat u.a folgende Propertie mitbekommen:

    Code
    public $decoratorClassName = SearchResultCar::class;

    Und in der Klasse SearchResultCar ist die $baseClass = Car::class; definiert.

    Dennoch schmeißt er mir durchgehend die o.g Fehlermeldung. Es ist sicherlich wieder irgendetwas "kleines" was ich übersehe, aber ich find's momentan einfach nicht.

  • Dann hat SearchResultCarList::$objectClassName entweder keinen Wert (=entspricht einem automatischen Fallback auf SearchResultCar) oder fälschlicherweise direkt SearchResultCar::class statt Car::class.

  • Nachdem ich den Fokus nun erst einmal darauf gelegt habe die Suche ans Laufen zu bringen (erstmal ohne decoratorClass), scheint dies erst einmal problemlos zu funktionieren über die existierenden Datenbank Objekte. Die Suche läuft, SearchIndexManager macht genau das, was er soll. ^^ Danke an alle an der Stelle erstmal.


    Fighter456:

    Ich schau mir morgen mal deinen Hinweis an. Besten Dank das du dich mit reindenkst! :) Ich hatte die SearchResultCarList so erstellt, wie derzeit die SearchPageContentList aussieht. Natürlich die entsprechenden Parameter abgeändert, leider ist dies jetzt über das Handy nicht mehr so einfach nachzuvollziehen. Danke nochmal!

    Besten Gruß

    JAY

  • Guten Abend zusammen,

    nachdem ich nun ein ganzes Stück weiter gekommen bin - Danke an alle an dieser Stelle - , stelle ich mir momentan die nachfolgenden Frage:

    1) Wenn ich eine neue Suchanfrage mit dem neuen ObjectType stelle, erhalte ich die SearchResultPage mit dem Template searchResultList. Dort würde ich gerne das Icon abändern. Im Template sehe ich bereits, dass die Variable $_messageCustomIcon überprüft wird. Nur: Wie setze ich diese? Ich habe dies bereits über die system/search/CarSearch Klasse probiert, klappt aber nicht. Oder ich mach es falsch. Die assignVariables() Methode dürfte ebenfalls keinen Effekt haben.

    https://github.com/WoltLab/WCF/bl…ultList.tpl#L18

    2) Besteht generell die Möglichkeit von 2 Controllern in das selbe Template zu rendern? (Auch für die Zukunft interessant)

    Ich hoffe jemand findet die Zeit, mir hier weiterzuhelfen. :)

    Besten Gruß

    JAY

    • Offizieller Beitrag
    1. Implementierte statt ISearchResultObject direkt das Interface ICustomIconSearchResultObject, das die zusätzliche Methode getCustomSearchResultIcon() bereitstellt.
    2. Ja, das ist prinzipiell möglich und wird von uns auch bei Templates zum Erstellen und Bearbeiten von Inhalten auch verwendet. Abseits von diesem Fall würde ich aber davon abraten und ggf. gemeinsame Inhalte in ein drittes Template auslagern und dieses dann mit {include file='…'} in beide Controller-Templates einbinden. Eine saubere 1:1-Zuordnung von Controller zu Template macht Dir in Zukunft das Leben einfacher.
  • Besten Dank Matthias Schmidt. Das hat super geklappt. Die Suche bei mir funktioniert jetzt. Ich möchte das Thema hier nicht überstrapazieren, aber wofür genau ist denn die Methode

    Code
    public function getFormattedMessage();

    im ISearchResultObject gedacht? Ich returne hier derzeit einfach fiktiv irgendeinen Wert (ohne Logik) und die Suche klappt trotzdem.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!