IIIF Presentation API v2のIIIFコレクションで、ページネーションを使う
概要
IIIF Presentation API v2のIIIFコレクションで、ページネーションを使う機会がありましたので、備忘録です。
背景
IIIFコレクションでは、以下のように、複数のマニフェストファイル(およびコレクション)の一覧を提供することができます。
{
"@context": "http://iiif.io/api/presentation/2/context.json",
"@id": "http://example.org/iiif/collection/top",
"@type": "sc:Collection",
"label": "Top Level Collection for Example Organization",
"viewingHint": "top",
"description": "Description of Collection",
"attribution": "Provided by Example Organization",
"manifests": [
{
"@id": "http://example.org/iiif/book1/manifest",
"@type": "sc:Manifest",
"label": "Book 1"
}
]
}
この時、対象とするマニフェストファイルが多数になった場合、一つのIIIFコレクションでは配信が難しくなりました。
これに対して、以下でページネーションに関する仕様がありましたので、こちらを使ってみます。
ページネーション
上記のページでは、以下のような例が紹介されていました。
{
"@context": "http://iiif.io/api/presentation/2/context.json",
"@id": "http://example.org/iiif/collection/top",
"@type": "sc:Collection",
"label": "Example Big Collection",
"total": 9316290,
"first": "http://example.org/iiif/collection/c1"
}
{
"@context": "http://iiif.io/api/presentation/2/context.json",
"@id": "http://example.org/iiif/collection/c1",
"@type": "sc:Collection",
"within": "http://example.org/iiif/collection/top",
"startIndex": 0,
"next": "http://example.org/iiif/collection/c2",
"manifests": [
// Manifests live here ...
]
}
まず、一つの目のJSONでコレクション全体のマニフェストファイル数total
を示し、さらにはじめの部分マニフェストファイル群へのリンクをfirst
で提示します。
first
で指定されたコレクションが2つ目のJSONであり、startIndex
とnext
を使って、現在の位置と次の部分マニフェストファイル群へのリンクを示すようでした。
DrupalとElasticsearchの組み合わせによる実装例
上記のようなページネーションについて、DrupalとElasticsearchの組み合わせによる実装例を紹介します。以下の記事で紹介したように、drupal/elasticsearch_connector
を使って、DrupalとElasticsearchを接続していることを前提とします。
Elasticsearchでは、from
を使ってオフセットを指定することができますが、max_result_window
(デフォルトでは、10,000件)を超える場合、正しく機能しません。
そこでsearch_after
を使って、特定のコンテンツに続くコンテンツを取得することができます。
例えば、特定のソート条件下で、20,000件目のコンテンツのID(field_id
)を取得し、以下のようなクエリにより、20,001件目以降のコンテンツを取得できます。searchAfter
に20,000件目のコンテンツのIDが入っています。
const query: SearchQuery = {
_source: ['title', 'field_manifest', 'field_id'],
size,
sort: [{ field_id: 'asc' }],
};
if (searchAfter) {
query.search_after = [searchAfter];
}
ただし、Elasticsearch単独で特定のソート条件下において、デフォルトのmax_result_window
を使う場合、例えば20,000件目のコンテンツのID(field_id
)を取得するには工夫が必要になります。
そこで、特定のソート条件下におけるxxx件目のコンテンツの取得、を行う部分については、DrupalのREST APIを使用しました。DrupalのViewsを使い、オフセットでユーザが指定指定できるようにした上で、1件のコンテンツを返却できるようにしました。
例:/api/xxx?offset=20000
これにより、search_after
に必要なコンテンツのIDを取得することができ、上述したElasticsearchへのクエリと組み合わせることで、ページネーションを含むIIIFコレクションを構築することができました。
参考
上記で実装したIIIFコレクションをPresentation API Validatorにかけてみました。
結果、上述したような、1つ目のコレクション全体を示すJSONでは、以下の警告が表示されました。
WARNING: Setting non-standard field 'first' on resource of type 'sc:Collection'
WARNING: Setting non-standard field 'total' on resource of type 'sc:Collection'
また、2つ目のコレクションの一部の示すJSONでは、以下の警告が表示されました。
WARNING: Setting non-standard field 'next' on resource of type 'sc:Collection'
WARNING: Setting non-standard field 'startIndex' on resource of type 'sc:Collection'
さらに、1つ目のコレクション全体を示すJSONについては、Universal ViewerやMiradorでもうまく表示させることができませんでした。
今回紹介した実装に問題があるのか等、引き続き調査してみたいと思います。
まとめ
IIIFコレクションを使って、多数のマニフェストファイル(またはサブコレクション)を提示する際に、本記事が参考になりましたら幸いです。
Discussion