Algoliaの検索結果レコード数の上限とページネーション

こちらはAlgolia Advent Calendar 2021の12月11日の記事です。お客様からお声がけいただくことが多い、検索結果レコード数とページネーションについて、AlgoliaドキュメントのPaginate Results in InstantSearch.jsを元にご紹介させていただきます。

Algoliaではページネーションについて、デフォルト値をIndex側に設定することができますが、それをクエリ時に上書きして置き換えることができます。

Index側のページネーションの設定

デフォルト値を以下の2つのパラメータで設定することができます。

  • hitsPerPage – ページ毎に返る検索ヒット数
  • paginationLimitedTo – ページネーションでアクセスできる最大の検索ヒット数(デフォルトは1000)

ダッシュボード上では👇の2つです。

クエリ側のページネーションの設定

  • 特定のページを page パラメーターを使って取得
  • offsetlength パラメーターを使って特定のレコードを取得
  • hitsPerPage パラメーターでデフォルトの値を上書き

クエリのレスポンスの詳細

検索結果のページネーションのために、Algoliaは現在の状態をJSONレスポンスに含めて返します。

{
  [...],
  "page": 0,
  "nbHits": 40,
  "nbPages": 2,
  "hitsPerPage": 20,
  "exhaustiveNbHits": true
}
  • page は現在のページ(注: 0からはじまります)
  • hitsPerPage は各ページで返るヒット数の最大値
  • nbPages は検索クエリの結果で利用可能なページの数
  • nbHits は検索クエリにマッチした結果の件数
  • exhaustiveNbHits はnbHitsがexhaustiveかapproximateかを示すboolean値(exhaustiveについては後述します)
  • exhaustiveTypo はtypo-tolerenceがexhaustiveかapproximateかを示すboolean値(typo-tolerenceが有効な場合のみ)

Exhaustivity

Algoliaはできるだけヒットした全体の正確な数を返そうとします。しかし、Exhaustiveよりもパフォーマンスを優先しなければならない場合もあります。クエリが膨大な数のレコードを返す場合に、Algoliaのエンジンは結果セット全体をスキャンすることを避け、おおよそ(approximate)の数を返します。このapproximateを返すという挙動は、他の検索やインデクシングの処理に影響を与えないようにするためのものであるとご理解いただけるとよろしいかと思います。また、別の方法としてbooleanのexhaustiveNbHitsを使って、この場合のヒット数を表示させないような微調整を施すことにもご利用いただけます。また、この事態が頻繁に発生するような場合は、データやIndexの設定をfine-tuneして全体的なパフォーマンスの向上を検討することもできるでしょう。

特定のページの取得

クエリ時に page パラメーターを渡すことで、検索結果のnページ目にダイレクトにアクセスすることができます。hitsPerPage パラメーターは、それぞれのページで返されるヒット数のデフォルト値を設定するためのものです。デフォルトでこの値は20となっていますが、Indexの設定もしくはクエリパラメーターで上書きすることができます。

index.search('query', {
  page: 2,
  hitsPerPage: 5
}).then(({ hits }) => {
  console.log(hits);
});

ページネーションの制限

クエリあたりのデフォルトのヒット数

デフォルトでは、Algoliaはクエリから取得できる最大のヒット件数の上限を1000に制限しています。この制限は最適なパフォーマンスを保証するためだけでなく、お客様のデータが簡単に外部に抽出されることを防ぐ目的もあります。通常ではデフォルトの1000で十分過ぎるほどであると思います。

デフォルトの制限値のオーバーライド

より多くのヒット件数が必要な特定のユースケース(eコマースのカテゴリーページや無限スクローリングのようなユーザー体験の開発など)においては、Index設定の paginationLimitedTo によって、デフォルトのページネーションの制限を引き上げることができます。

index.setSettings({
  paginationLimitedTo: 5000
});

重要

ページネーションの上限を増やすと、パフォーマンスに影響を与える可能性があります。本当に必要な分だけこの数値を増やすことを強くお勧めしています。

リミットを越えたページング

存在しないページ、もしくは、out-of-rangeなページ、つまり page >= nbPages をリクエストしても、Algoliaはエラーを返すことはなく、その代わりに0件の結果を返します。

レコードのサブセット(with offset and length)の取得

ページネーション機能を活用するには pagehitsPerPage を用いるのがベストプラクティスではありますが、ページネーションに影響を与えることなく、部分的にアイテムを検索結果の中に挿入したい(例えば広告など)場合があると思います。そのような場合には pagehitsPerPage を使うこともできますが、offsetlengthを使うことも可能です。

InstantSearchではすべてのページ処理のユースケースにおいて page と hitsPerPage を使って実装されています。

offsetlength パラメーターは、ページングの代わりに、ページではなく、検索するレコードを指定することができます。これには様々な理由があるものの、先ほど例でご紹介したように、結果の小さなサブセットの中に広告を入れ込みたい場合などがあります。

offset はhit(もしくはレコード)の開始を指定し、lengthで返されるレコードの数を指定します。

例えば、100件のレコードがあって、それが10ページに分割されている場合(hitsPerPage=10)、以下のようにペ0時を無視する形でレコードのサブセットを取り出すことが可能です(offsetは0ベースです)。

  • 50 から 80 までのレコード (offset=49 and length = 31)
  • 21 から 25 までのレコード (offset=20 and length = 5)

コメント

タイトルとURLをコピーしました