作ったページのコンテンツに対して検索をかける機能がほしかったので、algoliaのフリープランを使って全文検索できるページを追加した
index 用の json を生成
参考サイトのとおりに作った
config.toml
に以下を追加
[outputFormats.Algolia]
baseName = "algolia"
isPlainText = true
mediaType = "application/json"
notAlternative = true
[params.algolia]
vars = ["title", "summary", "content", "date", "publishdate", "description", "permalink", "keywords"]
params = ["tags", "categories"]
[outputs]
home = ["HTML", "RSS", "Algolia"]
# hugo v0.6以降はデフォルトでhtmlが表示されないためこちらの設定が必要
[markup.goldmark.renderer]
unsafe = true
出力する json のテンプレートは hugo のCustom Output Formatsを用いて行う
以下の設定を入れている
https://blog.piyo.tech/posts/2018-04-07-hugo-search-index/ より
本文を全部含めてしまうと Algolia の 1 データあたりのデータ上限を超えてしまうので、content は.Plain を 2000 文字で truncate するようにしました。また、サムネイルもを含めるようにしました
毎回全てのページを更新すると面倒なので、多分 30 日以内に作成した記事のみ json に出力している
後で作成する search ページを入れたくなかったので title が search のページを除外している
./src/layouts/_default/list.algolia.json
として以下を作成
{{/* Generates a valid Algolia search index */}}
{{- $.Scratch.Add "index" slice -}}
{{- $section := $.Site.GetPage "section" .Section }}
{{- range .Site.AllPages -}}
{{- $delta := now.Sub .Date -}}
{{- if or (and (.IsDescendant $section) (and (not .Draft) (not .Params.private))) $section.IsHome -}}
{{- if (le $delta.Hours 720) -}}
{{- if (and (eq .Kind "page") (ne .Title "search")) -}}
{{- $.Scratch.Add "index" (dict "objectID" .UniqueID "date" .Date.UTC.Unix "description" .Description "dir" .Dir "expirydate" .ExpiryDate.UTC.Unix "fuzzywordcount" .FuzzyWordCount "keywords" .Keywords "kind" .Kind "lang" .Lang "lastmod" .Lastmod.UTC.Unix "permalink" .Permalink "publishdate" .PublishDate "readingtime" .ReadingTime "relpermalink" .RelPermalink "summary" .Summary "title" .Title "type" .Type "url" .URL "weight" .Weight "wordcount" .WordCount "section" .Section "tags" .Params.Tags "categories" .Params.Categories "authors" .Params.Authors "content" (.Content | truncate 3000))}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- $.Scratch.Get "index" | jsonify -}}
これでhugo server
にてビルドしたときにpublic/algolia.json
に index 登録用の json が出力される。
生成した json を index に登録
手動でやるならば、algolia のダッシュボードに行き、 該当する index にて、json ファイルをアップロードすれば良い
自動更新用に、node.js でレコード登録用スクリプト作成
しかし、更新したときに自動でalgolia.json
を登録したい。このblogはnetlify
に自動デプロイ用のトリガーを設定しているため
ビルドに成功したら生成される json ファイルを登録するバッチ処理が走るように設定する
https://www.algolia.com/doc/api-reference/api-methods/add-objects/ を参考に作る
npm init
npm install --save algoliasearch
npm install --save dotenv
変数の管理は.env
で行う
APP_ID=xxxx
API_KEY=xxxx
INDEX_NAME=xxxx
var algoliasearch = require("algoliasearch")
require("dotenv").config()
// apiKey need addObject acl
const appId = process.env.APP_ID
const apiKey = process.env.API_KEY
const indexName = process.env.INDEX_NAME
const records = require("../src/public/algolia.json")
var client = algoliasearch(appId, apiKey)
var index = client.initIndex(indexName)
var res = index.addObjects(records)
netlify.toml
を編集して
hugo コマンドで build した後に node スクリプトを実行する
[build]
publish = "./src/public"
command = "hugo --gc --minify -s ./src --baseUrl='https://blog.uni-3.app' && cd ./algolia && npm install && node main.js""
のように&&
でつなげるだけ
search 用ページ作成
参考ページの通りにやっている
instantsearch.js
を使う。cdnのコードを適当な html へコピペする
hugo コマンドでsearch.md
を作成。コンテンツ一覧に出さないよう、showPagination
をfalse
にしておく
---
title: "search"
date: 2019-01-02T18:49:06Z
showPagination: false
---
<div id="search-box">
</div>
<ul id="hits">
</ul>
<div id="pagination">
</div>
<script>
// instantSearchを初期化
var search = instantsearch({
appId: 'X30EJUS2IA',
apiKey: '791937af7891a84d16eae4f9176bb7aa',
indexName: 'prod_blog',
urlSync: false
});
search.addWidget(
instantsearch.widgets.searchBox({
container: '#search-box',
placeholder: 'serch pages',
poweredBy: true
})
);
search.addWidget(
instantsearch.widgets.hits({
container: '#hits',
templates: {
empty: 'not found',
item: '<li><code>{{ dateString }}</code> <a href="{{permalink}}">{{ title }}</a></li>'
}
})
);
search.addWidget(
instantsearch.widgets.pagination({
container: '#pagination',
maxPages: 20,
scrollTo: false
})
);
search.start();
</script>
サイドバーから飛べるようにしたいのでconfig.toml
に以下を追加するこれは使用しているテーマにより設定方法が異なりそう。
[[menu.main]]
weight = 1
identifier = "search"
name = "Search"
pre = "<i class=\"sidebar-button-icon fa fa-lg fa-search\"></i>"
url = "/search"
これでひとまず検索用のページも作られる
参考
-
https://forestry.io/blog/search-with-algolia-in-hugo/
-
https://blog.piyo.tech/posts/2018-04-07-hugo-search-index/
-
https://blog.piyo.tech/posts/2018-04-08-hugo-search-page/
-
https://gohugo.io/functions
-
https://gohugohq.com/howto/compare-date-strings-in-hugo/
-
https://www.algolia.com/doc/api-reference/api-methods/add-objects/