ElasticPress Volltextsuche anpassen

Vor vier Wochen hatte ich euch ja berichtet, wie man Elasticsearch in WordPress verwenden kann und euch auch angekündigt, dass ich hierzu ein paar Artikel schreiben werde. Heute möchte ich damit beginnen und einen ersten kleinen Tipp geben, wie man die Volltextsuche optimieren kann.

Die Volltextsuche von Elasticsearch

Bei Elasticsearch werden alle Anfragen über die API abgewickelt. Hierbei kommt sowohl für die Anfrage, als auch für die Antwort JSON als Datenformat zum Einsatz. Abfragen werden in der Sprache Query DSL definiert. Eine Abfrage kann hierbei aus Queries und Filters bestehen. Diese unterscheiden sich in einigen Dingen, die wichtigsten möchte ich hier kurz auflisten:

Queries

  • Entscheidet die Frage, ob ein Text zu einer Suchanfrage passt
  • Beinhaltet eine Bewertung der Ergebnisse, wie gut diese zur Anfrage passen
  • Kann auch komplexere Volltext Suchabfragen abbilden

Filters

  • Wird nach der Query auf die Ergebnisse angewendet, filtert also nachträglich Ergebnisse raus
  • Bewerten die Ergebnisse der Abfrage nicht
  • Können gecached werden

Wenn man also eine sehr einfache Suchanfrage nach nur einem Wort macht, könnte man einen Filter verwenden. Im Allgemeinen bietet sich aber eine Query an, die erweiterte Suchen ermöglicht.

Varianten von Volltextsuchen

Bei der Volltextsuche mit einer Query kann man verschiedene Varianten wählen, wie mehrere Wörter kombiniert werden sollen. Dies sind die wichtigsten drei Varianten bei der Suche:

  • „and“: Jedes Suchwort muss im Text vorkommen
  • „or“: Nur eines der Suchwörter muss im Text vorkommen
  • „phrase“: Jedes Wort muss vorkommen, aber sie müssen auch nahe beieinander sein

Bei der Phrase-Variante ist es auch zusätzlich noch möglich anzugeben, dass nur ein bestimmter Prozentsatz der Wörter vorkommen muss. Eine solche Suche kann auch auf mehrere Felder angewendet werden. Dabei werden diese oft so definiert, dass sie vorkommen sollten („should“), aber nicht in jedem Feld vorkommen müssen.

Eine Suchanfrage in ElasticPress

In ElasticPress werden standardmäßig drei Volltextsuchen kombiniert, die auf die Felder Titel, Inhalt und Auszug eines Beitrags ausgeführt werden. Eine Abfrage davon verwendet „and“, eine „phrase“ und die letzte „or“ (da dies der Standard ist, wird es nicht angegeben).

"query": {
	"bool": {
		"should": [
			{
				"multi_match": {
					"query": "wordcamp berlin folien",
					"type": "phrase",
					"fields": [
						"post_title",
						"post_excerpt",
						"post_content"
					],
					"boost": 4,
					"fuzziness": 0
				}
			},
			{
				"multi_match": {
					"query": "wordcamp berlin folien",
					"fields": [
						"post_title",
						"post_excerpt",
						"post_content"
					],
					"boost": 2,
					"fuzziness": 0,
					"operator": "and"
				}
			},
			{
				"multi_match": {
					"fields": [
						"post_title",
						"post_excerpt",
						"post_content"
					],
					"query": "wordcamp berlin folien",
					"fuzziness": 1
				}
			}
		]
	}
},

Diese Kombination der drei Abfragen hat aber einen entscheidenden Nachteil. Die letzte Suche mit „or“ führt dazu, dass jeder Artikel gefunden wird, der einen der drei Begriffe enthält. Je mehr Wörter eine Suchanfrage also enthält desto mehr Beiträge werden gefunden.

Sucht man also in meinem Blog nur nach „WordCamp“, werden aktuell 27 Beiträge gefunden, bei „WordCamp Berlin“ sind es schon 44 Beiträge und bei „WordCamp Berlin Folien“ schließlich 48. Man würde aber doch erwarten, dass es weniger Beiträge werden, je genauer die Suche ist.

Suche bei mehreren Suchbegriffen einschränken

Ich sollte vielleicht noch anmerken, dass auch in der Standardeinstellung weitere Suchbegriff einen Vorteil bringen. Denn wie schon zuvor erwähnt werden Queries bewertet. Beiträge, in denen alle Begriffe vorkommen, werden also als erstes aufgeführt. Dennoch würde ich gerne nur solche Beiträge anzeigen lassen, in denen auch alle Begriffe vorkommen. Denn so ist man es auch von der WordPress-Suche ohne Elasticsearch gewohnt.

Leider bietet ElasticPress aktuell noch keinen Filter, mit denen man speziell die Query-Suche anpassen kann. Es ist aber möglich, die gesamte Abfrage zu verändern. Wir entfernen also einfach über einen Filter die letzte Suche aus der Query:

/**
 * Fine tune the arguments
 *
 * @param array $formatted_args The formatted args array for the query.
 * @param array $args           The raw query args array.
 *
 * @return array
 */
function elasticpress_tuning_ep_formatted_args( $formatted_args, $args ) {
	unset( $formatted_args['query']['bool']['should'][2] );
	return $formatted_args;
}
add_filter( 'ep_formatted_args', 'elasticpress_tuning_ep_formatted_args', 10, 2 );

Mehr ist wirklich nicht notwendig um die Suche zu optimieren. Nach dieser Anpassung werden bei der Suche nach „WordCamp Berlin Folien“ nur noch 4 Artikel gefunden und bei „WordCamp Berlin“ sind es noch 17. Das sind im Übrigen die gleichen Zahlen wie bei der normalen WordPress-Suche.

Fazit

Ich hoffe ich konnte euch mit diesem Beitrag einen ersten kleinen Einblick in die Technik hinter Elasticsearch und der Umsetzung von ElasticPress geben. Aber um euch nicht gleich mit diesem neuen Thema zu überfordern, soll es das für heute erst einmal gewesen sein 🙂 Wer sich ein bisschen mehr mit Query DSL und Elasticsearch beschäftigen möchte, der kann sich ja beispielsweise mal ein Video-Tutorial zu Query DSL ansehen. Aber ich freue mich natürlich auch wie immer über Fragen zum Thema, die ich in zukünftigen Artikeln aufgreifen kann.

Veröffentlicht von

Bernhard ist fest angestellter Webentwickler, entwickelt in seiner Freizeit Plugins, schreibt in seinem Blog über WordPress und andere Themen, treibt sich gerne bei den WP Meetups in Berlin und Potsdam herum und läuft nach Feierabend den ein oder anderen Halbmarathon.

Schreibe einen Kommentar

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