Contentfulの記事をAlgoliaのインデックスに登録する
全文検索SaaSのAlgoliaを試そうと思い、このブログに検索機能を追加した。
ContentfulとAlgoliaの連携方法については公式チュートリアルが用意されている。
導入手順
※ 前提:Algoliaのアカウントは作成済み
- Contetful APIを使って既存の記事データからAlgolia用のインデックスを生成する
- 記事作成、更新、削除時にインデックスが更新されるようにWebhookを設定する
- react-instantsearchを使ってアプリケーション側に検索機能を実装する
今回は手順1, 2についてまとめ、手順3は別記事にまとめる。
Contetful APIを使って既存の記事データからAlgolia用のインデックスを生成
Algoliaに登録するインデックスを↓と定義した。
{
url: "記事URL",
title: "タイトル",
description: "記事概要",
content: "MarkdownをPlainTextに変換した記事本文",
objectID: "Contentfulの記事ID",
}
Contetful APIを使って既存の記事データを取得し、上記定義に沿ったjsonを出力するscriptを作成。
// generate_algolia_index.js
const contentful = require("contentful-management");
const removeMd = require("remove-markdown");
(async () => {
const client = contentful.createClient({
accessToken: process.env.ACCESS_TOKEN,
});
const space = await client.getSpace(process.env.SPACE_ID);
const master = await space.getEnvironment("master");
const entries = await master.getEntries({
content_type: "blogPost",
limit: 1000,
});
const algoliaIndexes = entries.items.map((entry) => {
const indexFields = {
url: `/posts/${entry.fields.slug["ja-JP"]}`,
title: entry.fields.title["ja-JP"],
content: removeMd(entry.fields.body["ja-JP"]),
objectID: entry.sys.id,
};
if (entry.fields.description) {
indexFields.description = entry.fields.description["ja-JP"];
}
return indexFields;
});
console.log(JSON.stringify(algoliaIndexes, null, 2));
})();
上記scriptを実行し、適当なファイルにjsonを出力する。
node generate_algolia_index.js > algolia_index.json
Algoliaの管理画面のIndicesメニューからjsonファイルをアップロードする。
アップロードが完了すると管理画面上で登録済みのインデックスが確認できるようになる。
記事作成、更新、削除時にインデックスが更新されるようにWebhookを設定
Algoliaに登録したインデックス名と、API Keysメニューに記載されている
- Application ID
- Admin API Key
を確認しておく。
続いて、ContentfulのSettings => Webhooksを表示し、「See All 18 Templates」をクリックしてAlgoliaのテンプレートを表示する。
API Key等を入力しWebhook作成を実行すると、2つのWebhookが追加される。
- Algolia - Index entries
- Algolia - Delete unpublished entries
デフォルト設定だとAlgoliaに送信されるデータがContentfulのentryデータそのものになっているため、独自に定義したインデックスjsonと異なるjsonが登録されてしまう。
そこで、 Index entries
, Delete unpublished entries
それぞれの「Webhook settings」 => 「Payload」で「Customize the webhook payload」を選択し、独自定義のインデックスjsonを送信するように変更した。
{
"url": "/posts/{ /payload/fields/slug/ja-JP }",
"title": "{ /payload/fields/title/ja-JP }",
"description": "{ /payload/fields/description/ja-JP }",
"content": "{ strip-markdown /payload/fields/body/ja-JP }",
"objectID": "{ /payload/sys/id }"
}
MarkdownをPlainTextに変換するのをWebhookでどう実現しようかと思っていたが、 strip-markdown
という変換Helperが利用できた。
これで、ContentfulからAlgoliaへインデックス登録を行う仕組みができた。
次回はアプリケーション側での実装方法についてまとめる。
=> Next.js + Algoliaで全文検索UIを実装する