作ったページのコンテンツに対して検索をかける機能がほしかったので、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
生成した json を index に登録
手動でやるならば、algolia のダッシュボードに行き、 該当する index にて、json ファイルをアップロードすれば良い
自動更新用に、node.js でレコード登録用スクリプト作成
しかし、更新したときに自動で
algolia.json
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
[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
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"
これでひとまず検索用のページも作られる