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.

Abonnenten die Bearbeitung ihrer Kommentare erlauben

So langsam entwickelt sich das Thema Berechtigung ja zu einer kleinen Artikelreihe 🙂 Heute habe ich erneut ein hoffentlich spannendes Kapitel dazu im Angebot. In dem Projekt, das schon bei den letzten beiden Artikeln als Grundlage diente, gab es nun die Anforderung, dass Nutzer mit der Rolle “Abonnent” die Möglichkeit haben sollten, ihr Kommentare zu bearbeiten oder zu löschen.

Berechtigung zum Bearbeiten von Kommentaren vergeben

Ein kurzer Blick in den CODEX und die passende Rolle war gefunden. Das Hinzufügen einer Berechtigung zu einem Nutzer kann man nun entweder mit einem fertigen Plugin wie Members tun, oder aber mit wenig Code:

Weiterlesen →

Bilder in Mediathek auf aktuellen Nutzer beschränken

Letzte Woche hatte ich euch ja in einem Artikel beschrieben, wie ich in einem Custom Post Type “Portrait”, einem Nutzer ermöglicht habe, ein einzelnes Portrait bearbeiten zu können. Hierzu wurde auch eine eigene Rolle angelegt, mit der man die Berechtigungen besser steuern kann.

Nun gab es aber in diesem Projekt auch die Anforderung, dass ein Nutzer Bilder hochladen kann. Dabei gab es nun aber ein Problem. Wenn ich einem Nutzer erlaube, Bilder über die Mediathek hochzuladen, dann kann er auch die Bilder aller anderen Nutzer sehen. Das ist natürlich sehr unschön, gerade dann, wenn die Mediathek mit der Zeit sehr groß wird.

Nutzern den Upload von Bildern erlauben

Zuerst einmal musste ich natürlich der neuen Nutzerrolle generell das Recht einräumen, Bilder hochzuladen (ihr könnt aber natürlich auch eine bestehende Rolle wie “Abonnent” verändern):

Weiterlesen →

Eigene Rollen in der Autor-Box eines Custom Post Type anzeigen

Heute möchte ich euch einen kleinen Codeschnippsel an die Hand geben, der mir in der vergangenen Woche bei einem Problem mit den Berechtigungen geholfen hat. In einem Projekt sollte es Benutzern mit einer bestimmten Rolle ermöglicht werden, Seiten eines Custom Post Types zu bearbeiten. Die Einschränkung war hier allerdings, dass sie nur eigene Seiten des Custom Post Types bearbeiten dürfen.

Author-Box für Custom Post Type aktivieren

Eigentlich sollte das ja ganz einfach sein – dachte ich zumindest. Zuerst einmal muss man natürlich die Autor-Box für den Custom Post Type aktivieren. Nehmen wir einfach mal eine Portrait Seite als Beispiel. Dies geschieht bei der Registrierung des selbigen:

Weiterlesen →

Einrichtung von Elasticsearch in WordPress mit ElasticPress und Heroku

Am Donnerstag hatten wir unser erste WP Meetup Berlin in neuer Location. Dort habe ich einen kleinen Talk zum Thema Elasticsearch gehalten. Heute möchte ich euch zeigen, wie ihr Elasticsearch mit eurem Blog verwenden könnt. Es soll hierbei vor allem darum gehen, wie ihr schnell und kostenfrei eine Umgebung aufsetzen könnt, um mit Elasticsearch erste Experimente zu machen.

1. Installation eines Elasticsearch Servers

Wie ich in meinem Vortrag erläutert habe, handelt es sich bei Elasticsearch um einen “Suchserver”. Vergleichbar ist das mit einem MySQL Datenbankserver, den ihr ja ebenfalls für eine WordPress Installation benötigt und der irgendwo installiert und erreichbar sein muss.

Elasticsearch ist in Java programmiert und damit wird es nicht ohne weiteres möglich sein, diesen auf eurem Server zu installieren (sofern ihr überhaupt einen eigenen Server habt). Obwohl ich Elasticsearch direkt auf meinem Server installieren könnte, habe ich mich dagegen entschieden. Ich möchte ungern Java installieren und mich dann durch die Installation kämpfen.

Weiterlesen →