1. „ShOptiFind!“ -
Apache Solr
Integration in den
OXID eShop
Behind the Scenes – Fakten, Features,
Fallstricke, Lösungen
Stefan Moises, moises@shoptimax.de Shoptimax 2013
2. Apache Solr
Apache Solr
SolrTM is the popular, blazing fast open source enterprise search
platform from the Apache LuceneTM project. Its major features include
powerful full-text search, hit highlighting, faceted search, near real-
time indexing, dynamic clustering, database integration, rich
document (e.g., Word, PDF) handling, and geospatial search. Solr is
highly reliable, scalable and fault tolerant, providing distributed
indexing, replication and load-balanced querying, automated failover
and recovery, centralized configuration and more. Solr powers the
search and navigation features of many of the world's largest internet
sites.
17.03.2013
3. Apache Solr
• extrem performante, hochskalierbare, fehlertolerante Volltext-
Suche
• basiert auf Apache Lucene, entwickelt in Java
• Open Source
• sehr große Community
• weit verbreitet, viele Referenzen, u.a. Instagram, AT&T, AOL, The
Guardian, Ticketmaster, CNET, Gamespot, Sourceforge, Ebay
Kleinanzeigen, NASA, KaufDA, etc.
17.03.2013
10. SEO-fizierung der Filter-URLs etc.
ShOptiFind! verwendet seit Version 3.0 ausschließlich Filter in SEO-Form
Statt Kategorie-URLs mit Filter wie
„…/Kleidung/Jeans?oxattributeid=ade09099bfd909098&oxattr_val=gruen&…“
sieht eine gefilterte Kategorie nun z.B. so aus:
„../Kleidung/Jeans/Gruen/XS“
Die Canonical URL der Kategorie bleibt aber bei „…/Kleidung/Jeans“.
Dabei können die Filter auch in beliebiger Reihenfolge angeordnet sein, z.B. wird
die URL
„../Kleidung/Jeans/XS/Gruen “
automatisch „umgedreht“ und leitet auf die „korrekte“ (canonical) URL weiter.
17.03.2013
11. Addon: Landingpages
• Landingpages definierbar für beliebige Filter-Kombinationen, z.B. Kategorie
„Hosen“ und Attribut „Farbe“ mit Wert „Blau“
• Landingpages definierbar für Suchbegriffe (auch kombinierbar mit beliebigen
Filtern), z.B. Suche nach „Kite“ und Filter auf Hersteller XY
=> Landingpage z.B. „Kites von Hersteller XY jetzt 30 % günstiger“
• Landingpages können eine eigene CMS-Seite enthalten sowie alternative
Titel, Keywords und Beschreibung
17.03.2013
14. Backend-Integration
Import
CSV-Import
CSV-Export/Upload im Admin
Remote-Streaming von CSV-Daten
Manuell im Shop-Admin oder per
CRON
Datenbank-Import
Direkter Zugriff auf MySQL-Datenbank (ca. 500.000 Artikel / h)
Manuell / visuell im Admin oder per
CRON
Rich-Text-Import
Indizieren von PDF, DOC, PPT, MP3, etc. möglich
CMS-Inhalte
OXID CMS-Seiten können ebenfalls indiziert und durchsucht
werden
17.03.2013
19. Weitere Beispiel-Referenzen
Mercedes Benz Gebrauchtteile-Center
http://www.mbgtc.de
Partyschnaps - Spirituosen
Coler - Original-Autoteile versch. Marken/Hersteller http://www.partyschnaps.eu
http://www.originalteile.de
17.03.2013
20. Under the hood
Technische Details, Stolperfallen und Lösungen
17.03.2013
21. Under the hood - Technik
1. Technik – Allgemeine schematische Übersicht
OXID
CSV-
Export
SolrPHP-
MySQL
Client
DB-
Import
Solr /
Tomcat
17.03.2013
22. Under the hood – Solr Conf
• „fieldType“ und „field“ Elemente in schema.xml definieren
• „requestHandler“ usw. in solrconfig.xml definieren
17.03.2013
23. Under the hood – Solr Conf
• „db-data-config.xml“ erstellen, „entities“ definieren für DB-Import,
siehe 5.
17.03.2013
24. Under the hood - Problemlösungen
2. „3-Phasen-Suche“: Phrase-Query, reguläre Suche, Fuzzy
Problem / Herausforderung:
• Es soll erst möglichst genau gesucht werden (möglichst wenige,
aber „gute“ Treffer“)
• Erst wenn mit der „normalen“ Suche nichts gefunden wird, soll
„fuzzy“ gesucht werden
Lösung: „3-Phasen-Suche“:
„Phrase Search“
„jeans blau“
„normale Suche“
jeans blau
„Fuzzy Search“
jeans blau~
17.03.2013
25. Under the hood - Problemlösungen
• Wenn nichts gefunden wird, folgt jeweils der nächste Step
• Antwortzeiten von Solr im Vergleich zur Ladezeit des Shops
verschwindend gering
• Vom Solr-Ergebnis werden nur die OXIDs verwendet, damit wird
eine Standard-Artikel-Liste geladen
Vorteile:
• Standard Artikel-Funktionen und Artikel–Module sind
verfügbar
• Keine Template-Anpassungen für Liste oder Detailseite nötig
Nachteile:
• Evtl. Performance-Probleme bei sehr vielen Zugriffen
17.03.2013
26. Under the hood - Problemlösungen
3. Autocomplete / Suggest (JQueryUI)
Problem: Performance bei Verwendung des Shop-Frameworks
(View)! => direkte DB-Anbindung über Helper-Klassen
17.03.2013
27. Under the hood - Problemlösungen
4. Artikel-Varianten
Problem: keine Hierarchien in Lucene / Solr, d.h. jede Variante
wird einzeln ausgegeben, z.B. mehrfach dieselbe Jeans-Hose.
Varianten müssen aber indiziert werden, da sie ggf. eigene Texte
enthalten und eigene Attribute usw. haben!
Zwei Ansätze:
1. Daten aggregieren, Texte der Varianten zu Vaterartikel hinzufügen,
Attribute usw. kombinieren und alle Daten mit Vaterartikel speichern
2. Solr anpassen * / „Join-/Block-Join-Query“ nutzen: Varianten
eigenständig indizieren, für Rückgabe der Ergebnisse aber „Join“
durchführen und Artikel anhand der OXPARENTID „zusammenklappen“:
{!join from=oxparentid to=oxid}
Finale Query in Solr:
„{!join from=oxparentid to=oxid} _query_:{!edismax} Suchbegriff“
*) seit Version 4.x sind die sog. „JOIN-Queries“ Standard in Solr (siehe
http://wiki.apache.org/solr/Join), Block Joins kommen vorauss. erst in Solr 5.0
17.03.2013
28. Under the hood - Problemlösungen
Zusätzlich zu den JOIN-Queries zum „Zusammenklappen“ von
Varianten sind verschiedene Plugins für Solr nötig:
• SmxQueryComponent (fügt „join“ zur normalen Query hinzu)
• SmxMoreLikeThisComponent (blendet Varianten bei MLT aus)
• SmxFacetComponent (zeigt trotz Join-Query die Facets der
Varianten an, berechnet die korrekte Anzahl von Facets nach dem
Join)
plus einige Helfer-Klassen
17.03.2013
29. Under the hood - Problemlösungen
5. Datenaustausch
Probleme / Herausforderungen:
• CSV-Export kann sehr lange dauern / sehr groß werden
• Export sollte automatisiert laufen
• Export über SolrPHP-Client Objekte verbraucht zu viele
Resourcen / dauert zu lange
Versch. Lösungen:
• manueller CSV-Export im OXID-Admin mit Einschränkungen auf
Kategorien, Suchbegriffe, Bestand usw.:
17.03.2013
30. Under the hood - Problemlösungen
• zusätzlich automatisierbarer Batch-Export von CSV-Dateien
(schreibt Status-Datei und kann mehrfach per CRON o.ä. aufgerufen
werden, bis alle Artikel exportiert sind) – ohne SolrPHP-Client
• besser: alternative Importmöglichkeit über DIH (Solr
DataImportHandler Plugin)
=> Datenbank-Export, über XML definierbar mit Caching-Support für
SQL-Queries etc.
Tipp: „CachedSqlEntityProcessor“ nutzen! Beispiel:
<entity name="oxrealcats"
query="
SELECT
OXARTICLEID,
realpath
FROM
shoptifind_export_catpaths_${dataimporter.request.shopId}_${dataimporter.request.oxlang} cats
"
processor="CachedSqlEntityProcessor"
where="OXARTICLEID=oxarticle.OXID"
transformer="RegexTransformer"
>
<field column="catreal" splitBy="/" sourceColName="realpath" />
</entity>
(siehe http://wiki.apache.org/solr/DataImportHandler#CachedSqlEntityProcessor)
17.03.2013
31. Under the hood - Problemlösungen
6. Konfiguration von Solr über Shop-Admin
Probleme:
• Synonyme, Stop-Words usw. werden in .txt-Dateien auf dem
Suchserver konfiguriert, nach Änderungen muss der Solr-Core
neu geladen werden
• Sehr viele Einstellungen bzgl. Suche werden per GET-Parameter
an Solr übertragen, z.B. Felder für Facets, More Like This,
welcher Query-Parser verwendet werden soll etc.
Lösungen:
• Eigenes Java-Servlet, das die benötigten .txt-Dateien einlesen
und überschreiben kann („ShoptifindUtils“ als zusätzliche
Webapp)
17.03.2013
33. Under the hood - Problemlösungen
• Konfiguration der wichtigsten globalen Request-Parameter im
OXID Admin über „Array-style“ Eingabefelder, die mit „evil eval()“
im Modul ausgeführt werden:
17.03.2013
34. Under the hood - Problemlösungen
7. Weitere „Pitfalls“
• Vorsicht mit oxlocator::_setSearchLocatorData() bei vielen Artikeln – um
die Position im Suchergebnis zu bestimmen, wird
oxarticleList::loadSearchIds() aufgerufen, was per SQL wieder in
oxarticles, oxartextends, oxobject2category usw. „sucht“!
=> bei Klick auf Detailseite nach Suche teilweise Ladezeiten von 30
Sekunden!!
=> shoptifind_oxlocator Modul bestimmt Position über weitere Suche
Wenn Artikel „wenn ausverkauft, offline“ eingestellt hat
=> mit oxorder-Modul bei Kauf aus Index löschen, wenn Bestand = 0:
protected function _doXMLDelete($artId)
{
$data = array();
$data["stream.body"] = "<delete><query>oxid:$artId</query></delete>";
$this->_doXMLUpdate($data);
}
• UTF-8 Probleme
=> <form … accept-charset="utf-8„…
=> Tomcat Connector auf UTF-8 einstellen (tomcat/conf/server.xml)
17.03.2013
35. Under the hood - Problemlösungen
8. Exkurs: „SEO-Fizierung“ aller Filter
• Erzeugung von SEO-Begriffen (Umwandlung analog zu OXID) von
• oxvendor (Lieferanten)
• oxmanufacturers (Hersteller)
• oxcategories (Kategorien)
• oxattribute (Attribute)
• oxobject2attribute (Attributwerte)
• oxartextends.oxtags (Tags)
• Komplette De-Duplizierung aller SEO-Begriffe für Eindeutigkeit der SEO-Werte:
heißen z.B. zwei Kategorien sowie ein Attribut „Jeans“, werden die SEO-URLs wie
folgt erzeugt:
/Jeans/
/Jeans-/
/Jeans--/
=> jeder Begriff ist SEO-intern eindeutig und die Suche erkennt immer den
passenden Filter, ohne dass
• die Reihenfolge der URL-Parameter wichtig ist
• feste Keys verwendet werden (z.B. „/Hersteller/Adidas/Farbe/Blau“)
=> in ShOptiFind reicht: „/Adidas/Blau/“ oder „/Blau/Adidas/“
17.03.2013
36. Fragen?
Noch Fragen?
Noch Fragen?
Noch Fragen?
Noch
Fragen?
17.03.2013