開発者向け
Algolia、Rails、Kontent、Next.jsでヘッドレスコンテンツを検索する
By Tom Marshall
このゲスト記事では、KyanのTom Marshallが、関連する結果を返す魅力的で高速な検索エクスペリエンスを提供するプロセスについて説明します。
以前に検索機能を実装したことがある人なら誰でも知っているように、検索は一見複雑な問題です。グーグルは高い基準を設定しました。ユーザーは当然、入力の間違いや不正確さを許容しながら、検索エクスペリエンスが最初の数件の結果で求めているものを正確に返すと想定しています。
ユーザーの観点からは、検索は「正しく機能する」はずですが、それは口で言うほど簡単ではありません。
ヘッドレスCMSは、コンテンツをプレゼンテーション層から切り離します。それは多くの利点を提供します。それが私たちがヘッドレスを愛する理由ですが、検索機能にはそのプレゼンテーションの知識が必要です。コンテンツがどのように組み合わされてサイトのページを形成するかというこのコンテキストがなければ、ヘッドレスCMSは、箱から出してすぐにユーザーの期待に応えることができる検索ソリューションを提供できません。
ありがたいことに、AlgoliaのようなSearch-as-a-Service製品との統合は、ここでソリューションを提供します。
Kyanでは、魅力的で高速な検索エクスペリエンスを提供し、最も重要なこととして、関連する結果を返します。この記事では、私は、どのようにお見せしましょうAlgolia 、 Next.js 、 Ruby on Railsを、とKenticoによってKontent 。
私たちのシステムアーキテクチャ
WebフロントエンドとしてNext.jsプロジェクトがあります。これは、KontentヘッドレスCMSからコンテンツをフェッチし、Rails APIと通信して追加機能(コメントなど)を取得し、Algoliaのインスタント検索を統合して検索UIを提供します。
Kontentは正規のコンテンツストアですが、AlgoliaはKontent DeliveryAPIからリアルタイムで読み取ることはできません。それは遅すぎるでしょう。ローカルコピーが必要です。たとえば、夜間のcronジョブを使用して、コンテンツを定期的に一括でコピーすることもできますが、コンテンツの変更が公開されても検索結果の同期を維持する必要があります。
変更をプルするのではなく、プッシュする必要があります。
Kontentは、コンテンツの変更が公開されるとWebhook通知を発行しますが、生のKontentWebhook通知をAlgoliaに直接接続することはできません。これらのWebhook通知をリッスンし、検索に関連するコンテンツを抽出して、それをAlgoliaにプッシュするには、途中で何かが必要です。
Kyanでは、バックエンドサービスとAPIを構築するためのRailsが大好きなので、Railsアプリになりますが、Next.jsAPIエンドポイントまたはサーバーレス関数でもかまいません。 HTTPを話すものである必要があり、理想的にはKontentDeliveryおよびAlgoliaAPIで利用可能なオープンソースクライアントライブラリがありますが、それは必須ではありません。
インデックスの設計
Algoliaはコンテンツの完全なコピーを必要とせず、検索機能とUIに関連するフィールドのみを必要とします。必須のフィールドを決定するには、次の質問に答える必要があります。
必須のフィールド:
- 検索語を照合する場合
- 結果をフィルタリングするには
- 結果を注文するには
- 結果カードに表示するには
- そして最後に、参照に必要なID
例としてブログ記事を使用する:
検索用途 | 必要なフィールド |
検索語を照合する場合 | タイトルと本文 |
結果をフィルタリングするには | タグと作者 |
結果を注文するには | 公開日 |
結果を提示するため | 画像、推定読み取り時間、URLスラッグ |
参照用のID | KontentアイテムID |
一部のフィールドは複数のカテゴリに分類される場合がありますが、これは問題ありません。完全なセットが必要です。
検索機能に必要なフィールドがわかったので、Algolia内でインデックスを維持するようにRailsアプリケーションをセットアップできます。
インデックスの維持
コンテンツ編集者がKontentで変更を加えるとき、Webhookを介してAlgoliaに伝播する必要があります。その順序は次のとおりです。
アルゴリアの設定
Algoliaダッシュボードにログインしたら、新しいアプリケーションを作成する必要があります。この段階では、インデックスの作成やレコードのインポートについて心配する必要はありません。 algoliasearch-rails
がそれを処理します。 RailsおよびNext.jsアプリケーションのAPIキーを抽出する必要があります。
デモの目的で、Next.js用に事前に生成された「検索専用APIキー」とRailsアプリケーションの「管理APIキー」を使用します。本番環境では、アクセス制御を保護するための特定のAPIキーを作成し、レート制限、HTTPリファラーなどを指定する必要があります。
Webhook通知の処理
まず、Railsアプリケーションを作成し、必要な追加のgemを追加する必要があります。
config/initializers/algoliasearch.rb
追加して、Algoliagemを構成します。
次は、私たちのにそれらのAlgolia環境変数の値を追加してみましょう.env
:
AlgoliagemはRailsのActiveRecordORMのArticle
モデルを作成し、生成された移行を実行する必要があります。
>注:PostgreSQLを使用しているため、移行を実行する前にtags
属性を配列( t.string :tags, array: true, default: []
)になるように調整します。また、 tags
参照することができTag
モデルが、我々は唯一の現在戦とフィルタにタグ名を必要としています。
Algolia gemはActiveRecordの拡張機能として機能するため、 Article
レコードはPostgreSQLデータベースにローカルで自動的に保持されます。このデータベースの永続性は厳密には必要ないため、サーバーレス関数またはNext.jsAPIエンドポイントを使用している場合はスキップできます。ただし、このデータベースの永続性は、 algoliasearch-rails
gemがデフォルトで動作する方法であるため、Railsでの抵抗が最も少ないパスです。
algoliasearch-rails
メソッドを使用して、 Article
モデル属性をどのように使用するかを定義できます。
KontentからのWebhook通知は、選択したURLにPOSTされます。着信Webhookを処理するには、 config/routes.rb
ルートを追加する必要があります。
次に、そのルートのリクエストを処理するためのコントローラーアクションが必要です。
KontentのArticleアイテムへの変更からのWebhookリクエスト本文の例を次に示します。
リクエストの本文には、検索インデックスに必要なArticleアイテムのすべてのフィールドが含まれているわけではないことに気付くでしょう。代わりに、Webhookは変更されたコンテンツアイテムを列挙するだけです。これが、通知を受け取った後にKontentから完全なコンテンツをフェッチする必要がある理由です。
物事を管理しやすくするために、4つの異なるファイルにまたがるRailsロジックを分解します。
app/controllers/webhooks_controller.rb
着信HTTPリクエストを処理するためapp/lib/kentico/webhook_notification.rb
/webhook_notification.rb-Webhook通知内の記事アイテムを抽出するためapp/lib/kentico/fetch_content_item.rb
から完全なArticleアイテムコンテンツをフェッチするためapp/lib/kentico/article_item_response.rb
生のKontent応答をRailsモデル属性として提示するため
>注:本番アプリケーションでは、メインスレッドの過負荷を回避するためにここでバックグラウンドジョブを使用しますが、これはこのデモの範囲を超えています。
Kontentの設定
まず、Kontentにログインして、新しい空のプロジェクトを作成します。
次に、Webhookを作成する必要があります。
Kontent Webhook実装をローカルで開発およびテストするには、パブリックインターネットからの着信Webhookがローカル開発マシンに到達する必要があります。
ngrokは、ローカルマシンにトンネリングするWebhookのパブリックURLを提供できます。
Kontentプロジェクト設定でWebhookを作成し、URLをngrokからのトンネルURLとして設定します(例: https://d347-86-150-50-107.ngrok.io/webhooks/kentico
://d347-86-150-50-107.ngrok.io/webhooks/kentico)。
>注:Rails 6以降では、ngrokホストを開発構成に追加するか、 config.hosts.clear
をconfig/environments/development.rb
/development.rbに追加してホスト制限を完全に無効にする必要があります。
KontentプロジェクトのIDとウェブフック秘密を追加.env
Algolia環境変数と一緒に:
次に、ローカルRailsサーバーを起動します。
この段階で、コンテンツタイプを定義し、いくつかのテストコンテンツアイテムを作成する必要があります。 kontent-cli
を使用して、デモプロジェクトリポジトリのバックアップから復元して、これを手動で行わないようにすることができます。
>注:APIキーを生成するには、Kontentプロジェクト設定で管理APIを有効にする必要があり、 --name
パラメーターは自動的に.zip
サフィックスを適用します。
すべてが正常に機能している場合は、バックアップの復元によって新しく作成されたコンテンツアイテムのWebhookリクエストがトリガーされるためngrok
およびrails
完了すると、Kontentプロジェクトにデモコンテンツアイテムがあり、Railsデータベースに対応するArticleレコードがあります。
また、Web UIを介したAlgoliaインデックス(ハードリフレッシュが必要な場合があります):
デバッグ
問題が発生した場合、Kontentは各Webhookのデバッグログを提供してエラーを検査し、Webhookリクエスト本文をコピーします。これにより、PostmanやcURL
などのHTTPクライアントを使用してローカルでテストできます。
最後に、Next.js UI
Algoliaは、ライブ検索エクスペリエンスを構築するためのカスタマイズ可能なビルド済みコンポーネントのセットを提供するInstantSearchコンポーネントライブラリを提供します。フロントエンドはNext.jsアプリケーションであるため、InstantSearch forReactを使用します。
AlgoliaのInstantSearchドキュメントは、InstantSearchコンポーネントを組み合わせて、製品で機能する検索インターフェイスに構成する方法を説明する優れた仕事をしているため、ここでは取り上げません。代わりに、 Algoliaのビルド済みのNext.jsサーバー側レンダリングデモプロジェクトをプルし、デモ用にカスタマイズします。
yarn create next-app
が終了したら、2つのファイルをカスタマイズして、AlgoliaのデモプロジェクトをAlgoliaアプリケーションに接続する必要があります。
pages/index.js
のAlgolia検索クライアント構成を更新して、アプリケーションID、検索APIキーを環境構成からプルする必要があります。
そして、同じファイルで、 DEFAULT_PROPS
indexName
:
>注: algoliasearch-rails
gemを使用すると、インデックス名はデフォルトでモデル名になりますが、疑わしい場合は、インデックス名がAlgoliaWebダッシュボードに表示されます。
components/app.js
HitComponent
マークアップを更新して、デモのAlgoliaプロジェクトの属性ではなく、インデックスの属性を使用する必要があります。
次に、同じファイルで、ファセット属性を使用してRefinementList
メニューを更新します。
最後に、Next.jsとRailsのポート3000の両方のデフォルトは、その両方を同時に実行するために、あなたがする必要がありますNext.jsのためのポート上書きdev
中でスクリプトをpackage.json
。
これで、エンドツーエンドの検索ソリューションができました。 Next.jsアプリは、次のコマンドでローカルに起動できます。
そして、http:// localhost:3001のブラウザで表示します。
成功!
Kontentで公開されたコンテンツの更新はすべて、Railsを介してAlgoliaに自動的に伝播され、ユーザーは検索語を入力してファセット属性から選択するときに、結果をリアルタイムでフィルタリングできます。
自分で試してみたい場合は、GitHubでデモプロジェクトを見つけることができます。
追加クレジット
隠された複雑さ-モジュラーコンテンツ
現在、Railsアプリは、ユーザーがKontent内の記事コンテンツアイテムへの変更を公開すると、Algolia検索インデックスを更新します。ただし、ユーザーがブログ記事をタグと作成者で検索およびフィルタリングできるようにします。これらのコンテンツアイテムが変更された場合はどうなりますか?現在、何もありません。
タグまたは作成者が変更されたときに検索インデックスを更新するには、Webhook処理コードを更新して、タグと作成者のWebhook通知を破棄する代わりに、そのタグまたは作成者にリンクされているすべての記事アイテムを更新する必要があります。
KontentとAlgoliaを使用したモジュラーコンテンツのインデックス作成について詳しくは、Kontentブログをご覧ください。
バッチ同期
正規のソースからのデータのコピーを維持しているときはいつでも、完全なデータセットを更新するためのメカニズムを用意することが賢明です。このメカニズムは、初期データセットをロードするために使用できますが、将来的には、正規データの構造の変更後にすべてのレコードを更新する必要がある場合にも使用できます。
Railsアプリでは、このためのrakeタスクを追加します。このタスクは、すべてのArticleコンテンツアイテムをフェッチしてループし、Algoliaを更新します。
ただし、Kontent DeliveryAPIは応答ごとに最大2000アイテムに制限されていることに注意する必要があります。これにはリンクされたアイテムが含まれるため、リンクされたアイテムが含まれるデータを要求する場合、2000のチャンクでページングしてもエラーを防ぐことはできません。
簡単な解決策は、特定のコンテンツに基づいてこの値を調整する必要がありますが、2000を超えるアイテム(たとえば10)で応答がないことを確信できるほど小さいページサイズでループすることです。
より洗練されたアプローチは、増分バックオフを実装することです。これにより、最大アイテムエラーが発生した場合、リクエストは成功するまで小さいページサイズで再試行されます。このアプローチは成功を保証し、パフォーマンスも向上するはずですが、実装はより複雑です。
私たちは、人を動力源とするテクノロジーエージェンシーであるKyanです。