Elasticsearch mit PHP: Eine Suche für die Homepage
Im zweiten Teil über Elasticsearch erkläre ich Dir wie Du mit PHP auf die API zugreifest und eine erste Suche machst. Dazu gibt es ein paar Tipps, so dass auch Suchen mit Schreibfehlern zum Erfolg führen.
Im ersten Teil habe ich Dir erklärt, wie Du Elasticsearch auf einem Ubuntu Server installierst.
Elasticsearch PHP installieren
Die Installation des Elasticsearch PHP SDKs geht bequem über Composer. Dort erhältst Du Zugriff auf eine umfassende Bibliothek mit PHP Funktionen für den Zugriff auf Elasticsearch.
Du öffnest die Konsole, wechsle in das entsprechende Verzeichnis (z.B. /var/www/) und installiere Elasticsearch PHP:
cd /var/www/
composer require elasticsearch/elasticsearch
Unter /var/www/vendor/ wird jetzt der Ordner elasticsearch erstellt und alle Dateien heruntergeladen.
Elasticsearch PHP konfigurieren
Damit Du vernünftig und von überall problemlos auf Elasticsearch zugreifen kannst, baust Du Dir eine eigene Klasse "Elastic" in die alle Funktionen kommen:
require_once VENDOR.'autoload.php'; // VENDOR ist bei mir eine Konstante mit dem Pfad zu /var/www/vendor/
class Elastic{
public $es = false;
function __construct(){
$this->es = \Elasticsearch\ClientBuilder::create()
->setHosts([ 'IPELASTICSERVER:9200' ])
->build();
}
?>
In diesen wenigen Zeilen wird die Verbindung zum Elasticserver hergestellt. Du musst die Konstante VENDOR anpassen und natürlich statt IPELASTICSERVER die IP-Adresse eingeben auf der Elastc läuft (s. Tutorial 1).
Daten in Elasticsearch speichern mit PHP
Bevor Du Daten abfragen kannst, musst Du erstmal etwas abspeichern. Überleg Dir vorab, was Du alles speichern willst (bzw. wonach später gesucht werden soll). Bei mir schaut die Aufteilung so aus:
- index: example-com-de | Im Indexname kommt bei mir die URL vor (example-com) gefolgt von der Sprache (-de für Deutsch)
- type: blog | Der Type kann z.B. sein Blog, Produkt, Kategorie
- id: die ID des Eintrags in meiner MySQL Datenbank | Der Vorteil liegt darin, dass die ID sowieso nur einmalig vorkommt und ich dann sofort eine Querverknüpfung habe
- body: In den Body kommt der tatsächliche Inhalt. Das könnte sein: Title, Body (=Content des Blogs), MetaTitle, Teaser, etc.
Bist Du Dir im Klaren darüber wie die Struktur sein soll, kannst Du die Funktion zum speichern anlegen:
public function insert($p,$type='blog'){
if($type == 'blog'){
$params = [
'index' => $p->shopUrl.'-'.$p->lang,
'type' => $type,
'id' => $p->blogID,
'body' => [
'lang' => $p->lang,
'metaTitle' => $p->metaTitle,
'metaDescription' => $p->metaDescription,
'name' => $p->name,
'teaser' => $p->teaser,
'content' => $p->content
]
];
}
/*....*/
try{
// Alles hat geklappt
$indexed = $this->es->index($params);
return $indexed;
} catch (Elasticsearch\Common\Exceptions\BadRequest400Exception $e) {
// Speichern fehlgeschlagen
return false;
}
}
Das praktische ist: Wenn Du einen Eintrag updaten möchtest, kannst Du einfach die insert-Funktion verwenden. Sobange die ID identisch ist, wird der alte Beitrag einfach überschrieben. In $p sind alle Werte gespeichert die z.B. über ein POST-Formular kommen. Falls ihr sowohl einen Blog als auch eine Kategorie habt, könnt ihr über $type die IF-ELSE-Abfragen einfach weiter ausbauen.
Daten in Elasticsearch suchen mit PHP
Jetzt kommen wir zum spannenderen Teil, der Suche mit PHP und Elasticsearch.Auch das sind wenige Zeilen Code. Bzw. primär sind die Einstellungen wichtig, die man vornimmt:
public function search($q,$type='product'){
$query = $this->es->search([
'index' => 'example-com-de',
'type' => $type,
'body' => [
'query' =>[
'bool' => [
'must' => [
'multi_match' => [
'query' => $q,
'type' => 'phrase_prefix',
'cutoff_frequency' => '0.0007',
'operator' => 'or',
'fields' => ["name","metaTitle","metaDescription","teaser","content"]
]
]
]
]
]
'size' => 10,
'sort' => ['_score' => ['order' => 'desc']]
]
]);
return $query;
}
Das schaut jetzt ganz schön verschachtelt und unübersichtlich aus. Ist aber gar nicht so kompliziert. Im "Body"-Teil steht die eigentliche Suche. Alles darunter sind zusätzliche Einstellungen und Optionen. Aber der Reihe nach:
- body -> query -> bool -> must: Die eigentliche Abfage. "Bool" sagt aus, dass es sich um eine Abfrage handelt, die mehrere Abfragen kombiniert. "Must" ist der Teil, der zwingend vorkommen muss.
- multi_match: Ist eine Suchmethode, die mehrere Felder unabhängig von einander absucht und das Feld mit der besten Trefferquote wählt.
- query: In der Variable $q ist die Sucheingabe des Nutzers gespeichert. Danach wird gesucht.
- type: Hier wird die Art der Suche angegeben. phrase_prefix ist eine einfache Methode der Autovervollständigung und sucht entsprechende Teile ab. Dieser Type hat ein paar Tücken, ist aber gut genug für diesen Zweck.
- cutoff_frequency: Ignoriert sehr häufig vorkommende Worte sofern es Sinn macht (z.B.: der, die, das)
- operator: Die Art der Verknüpfung der Felder.
- fields: Die Felder in denen gesucht werden soll.
- size: Die Anzahl der Ergebnisse
- sort: Die Sortierung der Ergebnisse. In diesem Falle sortiert er absteigend beginnend mit dem besten Treffer.
Das war es auch schon. In $query ist dann die Rückgabe gespeichert. Die könnt ihr einmal per var_dump ausgeben und entsprechend die Felder wählen.
Einfache Abfrage mit Elasticsearch PHP
Die gespeicherten Werte zu einer ID abzufragen ist enorm simpel und Bedarf kaum einer Erklärung:
public function get($p,$type='blog'){
$params = [
'index' => 'example-com-de',
'type' => $type,
'id' => $p->id,
];
try{
$indexed = $this->es->get($params);
return $indexed;
} catch (Elasticsearch\Common\Exceptions\InvalidArgumentException $e) {
return false;
} catch(Elasticsearch\Common\Exceptions\Missing404Exception $e){
return false;
}
}
Wir suchen also einfach nur mit "->get" nach der ID und erhalten alle gespeicherten Werte dazu zurück. Spannender wird es bei einer tatsächlichen Suche.
Suche mit Rechtschreibfehlern in PHP
Als letzten Punkt gibt es noch ein Beispiel für eine Suche mit Rechtschreibfehlern (z.B. Elastcsearch statt Elasticsearch). Das ganze nennt sich "Fuzzy" in Elasticsearch. Er sucht also nach Worten die bis zu einem gewissen Grade dem Suchwort ähnlich sind.
Sucht ihr bei Glohbe nach Elastcsearch findet ihr in der Live-Suche nichts, erst druch das Drücken von "Enter" erscheint die Suche auf der Ergebnisseite. Das habe ich aus dem Grund eingebaut, dass die Fuzzy-Suche länger dauert und mehr Ergebnisse zurückliefern könnte, als gewünscht. Ein Beispiel:
[...]
'type' => 'fuzzy',
'body' => [
'query' => [
'bool' => [
'must' => [
'multi_match' => [
'query' => $q,
'type' => 'best_fields',
'cutoff_frequency' => '0.0007',
'operator' => 'or',
'fields' => ["name^5","metaTitle^3","metaDescription^2","teaser^2","content^1"],
"fuzziness" => "AUTO"
]
]
]
]
[...]
Wir haben also wieder ein must mit multi_match. Allerdings bei type "best_fields". best_fields ist ideal bei der Suche nach mehreren Wörtern in einem Field. Bei fields sind euch sicher die Hochzahlen (^5) aufgefallen. Das sind einfach die Gewichtungen. Kommt das Suchwort bereits im Artikelnamen vor, soll der Treffer stärker gewichtet sein, als wenn er im Content vorkommt. Fuziness ist der Abstand zwischen den einzelnen Buchstaben die fehlen dürfen, um ein neues Wort zu bilden. Bei Elasticsearch darf also das "i" fehlen, damit er Elastcsearch noch erkennt.
Fazit
Die Verknüpfung von Elasticsearch und Webseite über PHP ist sehr simpel und keine Wissenschaft. Die Feinabstimmung ist aber deutlich aufwendiger und sehr individuell. Die ganzen Werte und Einstellungen müssen auf die eigenen Anforderungen abgestimmt werden. Aber es ist so dennoch recht gut möglich eine sehr solide Suche auf die Beine zu stellen, die schonmal besser ist als 99% der Standardsuchen!
Weitere Artikel:
103 Bewertungen
1 Kommentar
19.09.2021 - Das Grundprinzip gut erklärt, aber ...
von: Padina
der Artikel vermittelt den Eindruck, dass die Einbindung von elasticsearch kein Hexenwerk ist.
Aber er lässt viele Fragen offen und gibt nocht nichteinmal Hinweis zur Lösung.
- Wo bekommt man mal eben für lokale Tests einen elastic-search-server her?
- wie funktioniert überhaupt eine Suche in Elastic? wo finde ich infos, um elasticsearch zu optimieren
Der Artikel ist gut, aber didaktisch zu stark reduziert. Es bleibt zu viel im Dunkeln.
Antwort von Johannes - 20.09.2021
Hallo Padina,
danke für dein Feedback.
Die Installation erkläre ich hier: https://www.glohbe.de/de/elasticsearch-v6-installation/
Wie man einen Server einrichtet, führt für dieses Tutorial zu weit.
Die Idee ist die Basics abzudecken. Wer sich weiter einarbeiten möchte. Bei tieferen Fragen bzw. für nähere Infos, hilft die Dokumentation: https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
Schöne Grüße
Bewertung:
War dieser Kommentar hilfreich?