Magento 2 und die liebe Suche

Magento LogoStolze Betreiber eines Magento 2 Shops kennen es vielleicht:

Die furchtbar schlechten Suchergebnisse der eigenen Suche zeugen von der scheinbaren Unfähigkeit der Entwickler, anständig mit MySQL umzugehen. Das ist nicht nur schade, sondern auch ziemlich frustrierend, hatte die 1.x-Version doch - ohne aufgesetztes Erweiterungsmodul - die exakt selben Probleme.

tl;dr Ein kurzes Statement zu ElasticSearch, sowie Code-Schnipsel, die der Magento 2 Suche durchaus weiterhelfen können. 

Zum Einen kann ich jedem Shop-Betreiber, der auf Magento 2 setzt, nur dringend empfehlen, auf ElasticSearch zu setzen. Die Suchergebnisse machen plötzlich viel mehr Sinn und es wird nicht stumpf scheinbar alles aufgelistet, was das Sortiment hergibt. Wer Angst vor Oracle hat, kann ElasticSearch auch perfekt mit dem OpenJDK betreibe. Das funktioniert hervorragend.

Zum Anderen bin ich auf folgendes Phänomen aufmerksam gemacht worden, das mir als Entwickler natürlich einleuchtet, das es so in 2019 aber nicht mehr unbedingt geben müsste.

Angenommen, ein Artikel hat die etwas sperrige Bezeichnung "212 AR" und Ihr habt Euch das genau gemerkt, damit Ihr im Netz danach suchen könnt. Ihr kennt da einen Online-Shop und hackt fröhlich "212AR" in die Suche (ohne Leerzeichen) und freut Euch - nicht.

Das ist ärgerlich und frustriert am Anfang, aber Ihr probiert es mit dem fehlenden Leerzeichen und findet alles - nur den Artikel nicht. Dieser Artikel ist auf Ergebnisseite 17 von 64 und Ihr habt bereits nach Seite 5 aufgegeben, da es scheinbar keinen Sinn macht, hier weiter zu suchen.

Handelt es sich bei dem Shop um eine Magento 2 Installation, findet die Suche vermutlich ohne ElasticSearch und ohne meinen kleinen "Hack" statt.

Um die Suche ohne Leerzeichen zu ermöglichen, habe ich mich eines kleinen Tricks bedient und die Magento "QueryFactory" überschrieben.

Und so wird's gemacht

Zunächst einmal habe ich ein neues Modul angelegt, das ich SplitSearch genannt habe. Dazu gibt es natürlich die üblich verdächtigen Dateien:

/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Search\Model\QueryFactory" 
        type="Codewerker\SplitSearch\Model\QueryFactory"/>
</config>

/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Codewerker_SplitSearch" 
        setup_version="1.0.0" />
</config>

/Model/QueryFactory.php

Hier habe ich tatsächlich einfach die original QueryFactory.php aus "/vendor/magento/module-search/Model" kopiert und den Namespace entsprechend angepasst.

Den Code um Zeile 114 herum, habe ich wie folgt ergänzt:

/**
 * @param string $queryText
 * @param int|string $maxQueryLength
 * @return string
 */
private function getPreparedQueryText($queryText, $maxQueryLength)
{

    $queryText = $this->trySplitting( $queryText );

    if ($this->isQueryTooLong($queryText, $maxQueryLength)) {
        $queryText = $this->string->substr($queryText, 0, $maxQueryLength);
    }
    return $queryText;
}

Und die Funktion "trySplitting" ebenfalls im Modul untergebracht:

private function trySplitting( $queryText )
{

    $originalQuery = $queryText;

    preg_match_all('/([0-9]+|[a-zA-Z\-]+)/', 
        $queryText, 
        $array );

    if( 0 < count( $array ) )
    {

        $result = $array[0];
        if( 1 < count( $result ) )
        {

            $queryText = implode( ' ', $result );
            return $queryText;

        }

    }

    return $originalQuery;

}

Nicht vergessen: Das Modul will registriert sein, ergo basteln wir noch schnell die Datei, die ich regelmäßig vergesse.

/registration.php

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Codewerker_SplitSearch',
    __DIR__
);

Here we go: Das war's schon.

Nachdem ich das Modul mit "bin/magento setup:upgrade" installiert hatte und den Cache fix säuberte, wurde die Suche bemerkenswert flexibler. Nun ist es völlig egal, ob man Artikelbezeichnungen, die aus Zahlen & Buchstaben oder gar Kombinationen aus Buchstaben, Zahlen und noch mehr Buchstaben, die vielleicht sogar noch mit Bindestrichen getrennt werden, bestehen. Das Suchergebnis ist nahezu identisch mit dem, das nach einer Suche mit Leerzeichen zwischen den Zeichen ausgegeben wird.

"212 AR" liefert die selben Ergebnisse, wie "212AR" und andersherum und - dank ElasticSearch - landen die wirklich besten Treffer an erster Stelle der Ergebnisliste.

Hurra!

Selbstverständlich steht es Euch frei, teure Erweiterungen im Marketplace zu kaufen, um bessere Suchergebnisse zu erhalten. Diese Variante erschien mir irgendwie simpler und vor allem günstiger.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert