Unser Weg zum Elasticsearch Plugin 1/2

Unser Weg zum Elasticsearch Plugin 1/2

Unser Elastic Search Plugin – so haben wir es gemacht: In diesem zweiteiligen Blog-Post geben wir dir einen Einblick in unsere Arbeit bei Inpsyde und wie wir für unsere Kunden wiederverwendbare, gut getestete, gut wartbare, erweiterbare und qualitativ hochwertige Plugins entwickeln können.

Unsere neunte Adventskalender-Tür offenbart: Den Weg zu unserem eigenen Elasticsearch Plugin – Teil eins. Inpsyder Christian Brückner, technischer Hauptentwickler dieses Projekts, wird erklären, was Elasticsearch ist, warum wir mit dem Bau eines eigenen Elasticsearch Plugins begonnen haben und wie wir das Problem angegangen sind.


Inhaltsverzeichnis:

Was ist Elasticsearch?
Warum ein eigenes Elasticsearch Plugin bauen?
Ein Team bilden
Das Kick-Off
1. Kenne deine Tools
2. Plugins reviewen
3. PHP-Packages reviewen
Das nächste Treffen
1. Review existierender Plugins
a. ElasticPress
b. SearchPress
c. JetPack Search
d. Algolia für WP
2. Review existierender PHP-Packages
a. Elasticsearch PHP (offiziell)
b. Elastica
c. WPES Lib
3. Entscheidungen Entscheidungen Entscheidungen


Was ist Elasticsearch?

Elasticsearch ist eine verbreitete RESTful Such- und Analysemaschine, die in der Lage ist, eine wachsende Anzahl von Anwendungsfällen zu lösen. Als Herzstück des Elastic Stacks speichert es deine Daten zentral, sodass du das Erwartete entdecken und das Unerwartete entdecken kannst.

Warum ein eigenes Elasticsearch Plugin bauen?

In der Vergangenheit haben wir viel mit den bestehenden Lösungen wie ElasticPress von 10up oder Jetpack Search von Automattic, das auf WordPress VIP gehostet wird, gearbeitet.

Diese Lösungen waren sofort gebrauchsfertig. Aber sobald wir die Suche anpassen oder versuchen mussten, die Speicherung der Daten in Elasticsearch für unsere Kundenprojekte zu verbessern, waren wir sehr unzufrieden. Am Ende schrieben wir eine Tonne Code, der Funktionen deaktivierte oder den wir um das Plugin herum entwickelten. Auch die Unterstützung eines modernen Tech-Stacks und die Nutzung neuester Technologien wie Composer, PHP 7 oder Elasticsearch 6 (seit November 2017) waren nicht gegeben.

Wir mussten unbedingt den Schritt nach vorne wagen und unsere eigene Lösung schreiben, die in Zukunft flexibel und einfach erweiterbar sein würde, ohne uns an andere Unternehmen zu binden und sich auf die kontinuierliche Weiterentwicklung des Plugins verlassen zu müssen.

Ein Team bilden

Bei Inpsyde haben wir derzeit drei Kundenteams, die nur an Kundenprojekten arbeiten und ein Produktteam, welches an Produkten wie MultilingualPress, BackWPup oder PayPal Plus arbeitet.

Um eine unternehmensweite Lösung für unsere Kunden zu erstellen, haben wir uns dazu entschieden, ein kleines Team zu bilden, welches aus drei Entwicklern von unterschiedlichen Teams und einem Projektmanager als Product Owner zur Leitung des Kommunikationsflusses und der Priorisierung unserer Ziele bestehen sollte.

Diese Zusammenarbeit zwischen den Teams geschieht immer wieder, um alle Anforderungen der Teams an eine Lösung zu erfassen. Unser Ziel ist es stets, keine isolierten Lösungen zu erstellen. Stattdessen wollen wir jeden an Board haben und brauchen auch jeden.

Nachdem wir nach ein wenig Zeit und Budget für das Projekt gefragt hatten, bildeten wir ein Team mit etwas Hintergrundwissen über Elasticsearch und über die bekannten Plugins:

  • Sebastian Pajor – Projektmanager und Product Owner
  • Christian Brückner – technischer Hauptentwickler
  • David Naber – Entwickler
  • Cristiano Baptista – Entwickler

Außerdem hatten wir immer wieder Hilfe von allen Teams, die unser Konzept überprüften und später Code Reviews durchführten.

Das Kick-Off

Bevor wir begannen, sammelten wir Anforderungen von allen Entwicklerteams. Diese Anforderungen wurden in unserem Kick-Off-Meeting vorgestellt und priorisiert:

  • Keine Magie – das Plugin sollte keine vorkonfigurierte Sofortlösung bieten
  • Einfach …
    • … zu erweitern
    • … zu konfigurieren
    • … neue Indizes zu erstellen
    • … Daten zu synchronisieren
    • … zu debuggen (logging)
  • Multisite Support
  • Möglichkeit, eine dataSource (z.B. WP_Post) zu mehreren Indizes zu pushen
  • asynchroner Umgang mit Datensynchronisation über Queue oder externe Message Handler wie RabbitMQ
  • WP CLI Support
  • Support der letzten Version von Elasticsearch (derzeit Version 6)
  • Sehr gute Abdeckung von Unit Tests

Außerdem entschied ich mich, ein Konzeptpapier in Google Drive zu erstellen, um alle Informationen, die wir benötigen, zu sammeln. Ich erstellte einen eigenen Slack-Kanal für eine schnellere Kommunikation und gab jedem bis zu unserem nächsten Treffen ein paar Hausaufgaben:

1. Kenne deine Tools

Da Elasticsearch nicht unser Hauptgeschäft ist, mussten wir eine gemeinsame Wissensbasis schaffen. Ziel war es, die gesamte Dokumentation durchzulesen, ein Glossar zu erstellen und zu fragen, wenn etwas unklar ist. Dies war wichtig für die weiteren Schritte, damit jeder weiß, was wir integrieren müssen:

  1. Die Dokumentation lesen https://www.elastic.co/guide/en/Elasticsearch/reference/6.x/index.html
  2. Gemeinsam ein Glossar schreiben
  3. Niederschreiben, was unsere Lösung zu unterstützen hat: Cluster, Nodes, Shard, Indizes, Typen, Mapping, Dokumente, Repliken und in ein paar Sätzen beschreiben.
  4. Über alles diskutieren und immer Fragen stellen!

2. Plugins reviewen

Ich habe beschlossen, die folgenden Plugins aufzuteilen, sodass jeder ein kurzes Audit, eine Review und ein Fazit erstellen muss:

  • ElasticPress
  • SearchPress
  • JetPack Search
  • Algolia für WP

Die Ergebnisse stellte jedes Teammitglied im nächsten Meeting vor. Dieser Schritt ist sehr wichtig, denn wir müssen die Stärken und Schwächen bestehender Plugins kennen und was wir daraus lernen können.

3. PHP-Packages reviewen

Da wir Composer als Dependency Management verwenden, mussten wir uns entscheiden, ob es möglich ist, bestehende Lösungen wiederzuverwenden, um mit der Elasticsearch API zu kommunizieren oder ob wir die Verbindung zur API von Grund auf neu schreiben müssen. Deshalb … mehr Hausaufgaben für alle: Jedes Teammitglied musste eines der folgenden Packages überprüfen:

  • Elasticsearch PHP – das offizielle PHP Package von Elasticsearch.
  • Elastica – einen übergeordneten Wrapper um den Client herum
  • WPES Lib – extrahiertes automatisches Package von JetPack Search.

Das nächste Meeting

Nach einiger Zeit haben wir ein zweites Treffen geplant, um über unsere Ergebnisse und Forschungen zu sprechen. Da jede Review mindestens 1,5 Seiten lang ist, werde ich versuchen, kurz zusammenzufassen, was wir herausgefunden haben:

1. Review existierender Plugins

Alle aufgeführten Plugin-Lösungen bieten “Push Data to Elastic” und “Change Default WP_Query” out of the Box, was vielleicht für verschiedene Seiten und Szenarien hilfreich ist, aber bei vielen benutzerdefinierten Daten und Regeln für die Suche durch die Daten schwierig sein wird. Außerdem unterstützen alle Plugins nur WP_Post als Startpunkt. Es gibt nicht immer von vornherein Support für WP_User, WP_Comment oder WP_Term, um in einen eigenen Index für Elasticsearch zu gelangen.

Das Auto-Parsing von WP_Query in einen Elasticsearch-API-Call ist hinsichtlich der “Transformation” nicht immer zu 100% korrekt. Dies kann die Suche mit falschen Ergebnisse überfluten.

Alle Plugins missbrauchen Elasticsearch als eine Art “Caching”-Layer zu MySQL, um zu behaupten, dass die Performance gesteigert wird. Ja, die Performance wird erhöht, wenn eine langsame, falsch konfigurierte Datenbank ohne Caching vorliegt. Aber das Hauptziel ist nicht “Caching der Ergebnisse”, sondern “Suchen”.

Als kleine Erinnerung, der Hauptunterschied von RDBMS und Elasticsearch ist:

RDBMS beantwortet die Frage: Welches sind die Dokumente, die perfekt zu den Werten passen, die in die Query eingefügt wurden?

Suchmaschinen (wie Lucene) beantworten die Frage: Welche sind die ähnlichsten Dokumente zur Abfrage, geordnet nach einem Relevanzwertindex?

Hier ist eine kurze Übersicht über unsere Review:

[toggle title=”ElasticPress”]

ElasticPress

Link: https://github.com/10up/ElasticPress

ElasticPress ist eine sehr bekannte und häufig genutzte Lösung. 10up bietet außerdem ein eigenes gehostetes Elasticsearch https://www.elasticpress.io/ an.

Wenn es aktiviert ist und die Anmeldeinformationen konfiguriert sind, sendet das Plugin automatisch Daten zu Elasticsearch und ersetzt die WP_Query.

Wir haben dieses Plugin in der Vergangenheit viel benutzt und angepasst und mitgearbeitet, indem wir Issues im offiziellen Repository erstellt haben. Und das ist genau der Ausgangspunkt, warum wir uns für ein eigenes Plugin entschieden haben. Es gibt für uns keinen “Fortschritt” mehr. Wir enden immer damit, um Code-Probleme herum zu schreiben.

Das Plugin ist immer noch auf PHP 5.2 Level mit viel Spaghetti-Code (z.B. ep_wc_translate_args() hat eine zyklomatische Komplexität von 63, npath eine Komplexität von 26203564800 und eine Länge von 328 Zeilen). Es hat keine Logging Integration, hat keinen (offiziellen) Support für die neueste Elasticsearch-Version (06/2018) und ist sehr schwer erweiterbar.
[/toggle]
[toggle title=”SearchPress”]

SearchPress

Link: https://github.com/alleyinteractive/searchpress

SearchPress von alleyinteractive wird derzeit nicht aktiv gewartet. Der letzte Commit erfolgte im März 2018 (als wir ihn im Sommer überprüften) und war der einzige Commit in diesem Jahr.

Das Plugin selbst verwendet viele Globals, basiert auf PHP 5.3 und hat einige fragwürdige Konzepte, die Fehler hervorrufen können, indem u.B. das Mapping geändert wird. Das Plugin erstellt automatisch ein Mapping, welches Post-Daten zu Elasticsearch pusht/synct. In WordPress ersetzt es die WP_Query und versucht, Ergebnisse von Elasticsearch zu laden.
[/toggle]
[toggle title=”Jetpack Search”]

JetPack Search

Link: https://jetpack.com/support/search/

Link: https://github.com/Automattic/jetpack/tree/master/modules/search

Die JetPack-Suche wird auch häufig in Kombination mit JetPack und einer empfohlenen und vorinstallierten Lösung genutzt, wenn man WordPress VIP oder WordPress VIP Go Hosting verwendet.

Das Hauptproblem bei diesem Plugin ist, dass es noch keinen Support für die neueste Elasticsearch Version gibt und dass man das gesamte JetPack-Ökosystem mit “Jetpack Professional Plan” installieren muss, um nur das Suchmodul zu verwenden. Der Code ist wirklich sehr WordPressy, erlaubt aber zumindest das Debuggen mit einigen bekannten Tools wie Debug Bar und Query Monitor. Trotzdem gibt es einige gut durchdachte Features und das Schema deckt viele Anwendungsfälle ab, aber wir wollen uns nicht auf das riesige JetPack-Ökosystem verlassen müssen und WP_Query automatisch durch das Plugin ersetzen.
[/toggle]
[toggle title=”Algolia for WP”]

Algolia für WP

Link: https://github.com/algolia/algoliasearch-wordpress

Das Plugin bietet Zugriff auf https://www.algolia.com/, eine Art gehostete Elasticsearch mit eingeschränkten Funktionen. Die Konfiguration erfolgt über die Backend-Einstellungsseite und erfordert ein Algolia-Konto. Die Daten werden automatisch nach Algolia übertragen, können aber nicht geändert werden. Auch der Service selbst kostet eine monatliche Gebühr. Das Plugin bietet standardmäßig eine Autovervollständigung für die WordPress-Suche im Frontend und einige benutzerdefinierte Skripte.

Wir haben auf eine eingehende Überprüfung verzichtet, da dieses Plugin uns zu sehr einschränken würde und wir uns immer auf den externen Service verlassen müssten. Zumindest die Konzepte und die Umsetzung waren gut zu sehen und es war gut, sie für die spätere Arbeit zu kennen.
[/toggle]

2. Review existierender PHP Packages

Wir haben uns für das offizielle “Elasticsearch PHP Package” entschieden, das die vollständige Unterstützung der API, eine moderne PHP-Version und die kontinuierliche Weiterentwicklung der Funktionen bietet. Da wir die API in unserem Plugin abstrahieren werden, sind wir zukunftssicher und können, wenn gewünscht, das Package leicht ersetzen.

Hier ist eine kurze Übersicht unserer Review:

[toggle title=”Elasticsearch PHP”]

Elasticsearch PHP (offiziell)

Link: https://github.com/elastic/Elasticsearch-php

Dies ist das offizielle PHP-Package, das die komplette API zu Elasticsearch unterstützt. Es wird aktiv weiterentwickelt, benötigt PHP >= 7, hat Composer Support und ist eine Art Low-Level-Abstraktion der API mit einfacher Konfiguration des Clients. Außerdem unterstützt es das Logging über die PSR-3 LoggerInterface https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md out of the box.
[/toggle]
[toggle title=”Elastica”]

Elastica

Link: https://github.com/ruflin/Elastica

Dieses Package ist ein Wrapper um den offiziellen Client, wird aktiv entwickelt und hängt vom offiziellen Elasticsearch PHP Package ab.

Das Package bietet eine benutzerfreundlichere API, die ziemlich einfach zu bedienen ist, aber die weitere Entwicklung ist offen und kann uns behindern, da wir uns zu sehr auf spezifische Implementierungen verlassen würden.
[/toggle]
[toggle title=”WPES Lib”]

WPES Lib

Link: https://github.com/Automattic/wpes-lib

Dieses Package von Automattic ist ein minimalistischer Ansatz, um mit Elasticsearch zu kommunizieren. Leider hat es keinen integrierten Composer- und Logging Support und deckt nicht die gesamte API ab. Außerdem fehlt es an Unit-Tests und ist im “alten PHP-Stil” wie WordPress geschrieben. Zu guter Letzt wird in der Dokumentation erwähnt, dass “wahrscheinlich Elasticsearch 5.x” unterstützt wird. Das war im Oktober 2016.
[/toggle]

Entscheidungen Entscheidungen Entscheidungen

Nachdem wir unsere Zusammenfassungen geschrieben und alle unsere Ergebnisse durchgesehen haben, haben wir schließlich einige Entscheidungen für die folgenden Schritte getroffen:

  1. Wir reden in der gleichen Sprache, wenn wir über Elasticsearch sprechen.
  2. Die bestehenden Lösungen mit ihren Stärken und Schwächen sind uns bekannt.
  3. Wir werden das offizielle “elasticsearch-php”-Package nutzen, um mit der API zu sprechen.
  4. Wir brauchen einen Namen für das Baby.
  5. Um Arbeit aufzuteilen, werden wir Module unseres neuen Plugins definieren.

Bleib gespannt, denn in meinem nächsten Blogpost werde ich dir ein paar Einblicke über die grundsätzlichen Konzepte, denen wir gefolgt sind, geben und dir beschreiben, wie wir implementiert haben!