Suchindex mit GoHugo für Meilisearch erstellen
Meilisearch bietet neben ElasticSearch und Solr eine schlanke Alternative zur Suche. Die Konfiguration und Einbindung werde ich ggf. in weiteren Beiträgen erläutern.
Für die Suche können mehrere Suchindexe definiert werden. Diese basieren auf Dokumenten. Ich habe ausprobiert diesen Index direkt beim Generieren der Seite mit GoHugo zu erzeugen.
Format Konfigurieren link
In der Konfiguration von GoHugo können outputs
und outputFormats
definiert werden. Wenn diese nicht gesetzt sind, werden HTML
und RSS
als Standard verwendet. Eine Liste aller verfügbaren Typen und Standardformate ist in der [Hugo Dokumentation] (https://gohugo.io/templates/output-formats/) zu finden.
Zuerst definiere ich ein eigenes Format als outputFormat
. Dieses wird jeweils in einem Unterordner /search
ausgegeben. Bei Verwendung des Languages-Moduls ist der Pfad z.B. /de/search
.
# config.yaml
outputFormats:
Meilisearch:
name: meilisearch
baseName: all
isPlainText: true
mediaType: application/json
notAlternative: true
path: search
Als nächstes muss definiert werden, welche Seitentypen wie gerendert werden sollen. Die Idee meines Ansatzes ist es, nur die Startseite als Suchindex zu rendern. GoHugo stellt den gesamten Inhalt zur Verfügung. Es wäre auch möglich, Seiten, Artikel, Begriffe und Taxonomien einzeln zu rendern, aber diese müssten alle einzeln an Meilisearch zurückgeschickt werden.
Die anderen Seiten werden weiterhin in den Standardformaten (HTML
, RSS
) generiert, sofern in der Liste nicht anders angegeben.
# config.yaml
outputs:
home:
- HTML
- Meilisearch
Layout Templates link
Für das eigene Ausgabeformat habe ich ein eigenes Template erstellt. Die Config-Einstellungen name: meilisearch
und der mediaType: application/json
erwarten eine Template-Datei layouts/_default/home.meilisearch.json
. Mit home
steuere ich, dass nur die Startseite in einer einzelnen Datei gerendert wird.
Um ein korrektes JSON-Dokument zu erzeugen, darf hinter dem letzten Eintrag kein Komma stehen. Dies wird mit einem Trick erreicht.
[{{ range $pageIndex, $page := (where .Site.Pages "Type" "in" (slice "article" "glossar")) -}}
{{- if $pageIndex }},{{ end }}
{
"_kind": "{{ $page.Kind }}",
"_type": "{{ $page.Type }}",
"url": "{{ $page.Permalink }}",
"id": "{{ $page.File.UniqueID }}",
"language": "{{ $page.Language }}",
"content": {{ (strings.Replace $page.Plain "\n" " ") | htmlUnescape | jsonify }}
}
{{- end }}
]
Mit dem Slice (slice "Artikel" "Glossar")
kann definiert werden, welche Artikeltypen eingebunden werden sollen. Der Typ kann im FontMatter der Markdown-Dateien mit type
festgelegt werden.
Für den Content wird .Plain
verwendet. Diese Variable enthält den Inhalt ohne HTML oder Markup für Überschriften. Sonderzeichen sind HTML escaped. Mit htmlUnescape
werden sie wieder in normale Zeichen umgewandelt. Mit jsonify
wird aus dem String ein JSON-String, inklusive Escape von JSON-Befehlszeichen wie "
.
Breadcrumb link
Wenn dem Dokument übergeordnete Rubriken zugeordnet werden sollen, ist dies ebenfalls sehr einfach möglich.
[{{ range $pageIndex, $page := (where .Site.Pages "Type" "in" (slice "article" "glossar")) -}}
{{- if $pageIndex }},{{ end }}
{
...
"id": "{{ $page.File.UniqueID }}",
"sections": [
{{- range $i, $e := after 1 $page.Ancestors.Reverse -}}
{{- if $i }},{{ end }}
{
"title": "{{ $e.LinkTitle }}",
"url": "{{ $e.Permalink }}"
}
{{- end }}
],
"language": "{{ $page.Language }}",
...
}
{{- end }}
]
Für jede Seite sind die übergeordneten Rubriken in der Variable .Ancestors
enthalten. Mit after 1
wird der erste Eintrag übersprungen, da dies die Startseite ist.
Tags link
Tags, Kategorien oder andere Parameter aus dem FontMatter können wie Rubriken hinzugefügt werden.
[{{ range $pageIndex, $page := (where .Site.Pages "Type" "in" (slice "article" "glossar")) -}}
{{- if $pageIndex }},{{ end }}
{
...
"id": "{{ $page.File.UniqueID }}",
"tags": [
{{- range $i, $e := $page.Params.Tags -}}
{{- if $i -}}, {{ end -}}
"{{$e}}"
{{- end -}}
],
"language": "{{ $page.Language }}",
...
}
{{- end }}
]