これらの最適化の推奨事項を適用する前に、最高のパフォーマンスを実現するには、GraphQL フィルタリングでのページングと並べ替えの際にコンテンツフラグメントを更新することを検討してください。
同じモデルを共有するコンテンツフラグメントが多数ある AEM インスタンスでは、GraphQL のリストクエリに(リソースの点で)コストがかかる場合があります。
これは、GraphQL クエリ内で使用されているモデルを共有するすべてのフラグメントを、メモリに読み込む必要があるためです。これは時間とメモリの両方を消費します。 結果セット全体をメモリに読み込んだ後にのみ、(最終的な)結果セット内の項目数を減らす可能性のあるフィルタリングを適用できます。
これにより、小さな結果セットでもパフォーマンスが低下するというインプレッションを与える可能性があります。ただし、実際には、フィルタリングを適用する前に内部で処理する必要があるので、初期結果セットのサイズが原因で速度が低下します。
パフォーマンスとメモリの問題を減らすには、この初期結果セットをできるだけ小さく保つ必要があります。
AEM には、GraphQL クエリを最適化する 2 つの方法があります。
各アプローチには、独自のユースケースと制限があります。 このドキュメントでは、ハイブリッドフィルタリングとページングに関する情報と、GraphQL クエリを最適化するベストプラクティスについて説明します。
ハイブリッドフィルタリングは、JCR フィルタリングと AEM フィルタリングを組み合わせます。
結果セットを AEM フィルタリング用のメモリに読み込む前に、(クエリ制約の形式で)JCR フィルターを適用します。 これは、JCR フィルターによって余分な結果が先に削除されるので、メモリに読み込まれる結果セットを減らすためです。
技術的な理由(柔軟性、フラグメントのネストなど)により、AEM はフィルタリング全体を JCR に委任できません。
この方法では、GraphQL フィルターが提供する柔軟性を維持しながら、可能な限り多くのフィルタリングを JCR に委任できます。
AEM の GraphQL では、次の 2 種類のページネーションに対応しています。
制限/オフセットベースのページネーション
これは、リストクエリに使用されます。これらは次の値で終わります
List
(例:articleList
)。
これを使用するには、最初に返す項目(offset
)と返す項目の数(limit
またはページサイズ)を指定する必要があります。
カーソルベースのページネーション(first
および after
で表される)
これにより、項目ごとに一意の ID が提供されます。「カーソル」とも呼ばれます。
クエリでは、前のページの最後の項目のカーソルとページサイズ(返される項目の最大数)を指定します。
カーソルベースのページネーションはリストベースのクエリのデータ構造内に収まらないので、AEM では Paginated
クエリタイプ(例: articlePaginated
)を導入しました。 使用するデータ構造とパラメーターは、GraphQL Cursor ConnectionSpecification に準拠します。
AEM は現在、前方ページングをサポートしています(after
/first
パラメーターを使用)。
後方ページング(before
/last
パラメーターを使用)はサポートされていません。
並べ替えは、すべての並べ替え条件が最上位のフラグメントに関連している場合にのみ効率的です。
並べ替え順に、ネストされたフラグメントに配置された 1 つ以上のフィールドが含まれている場合、最上位モデルを共有するすべてのフラグメントをメモリに読み込む必要があります。 これにより、パフォーマンスが低下します。
最上位フィールドでの並べ替えも、(小さくても)パフォーマンスに影響を与えます。
すべての最適化での主な目的は、初期結果セットを減らすことです。 ここに示すベストプラクティスで、その方法を説明します。 組み合わせることができます(推奨)。
現在、JCR レベルでのフィルタリングは、最上位のフラグメントに対してのみ機能します。
フィルターがネストされたフラグメントのフィールドに対応する場合、AEM はフォールバックして、基になるモデルを共有するすべてのフラグメントを(メモリに)読み込む必要があります。
最上位のフラグメントのフィールドとネストされたフラグメントのフィールドのフィルター式を、AND 演算子と組み合わせることで、このような GraphQL クエリを引き続き最適化できます。
AEM では、通常、リポジトリ構造を使用して、処理するコンテンツの範囲を絞り込むことをお勧めします。
この方法は、GraphQL クエリにも適用する必要があります。
これを実行するには、最上位フラグメントの _path
フィールドにフィルターを適用します。
{
someList(filter: {
_path: {
_expressions: [
{
value: "/content/dam/some/sub/path/",
_operator: STARTS_WITH
}
]
}
}) {
items {
# ...
}
}
}
最高のパフォーマンスを得るには、value
の末尾に /
を付ける必要があります。
ページングを使用して、初期の結果セットを減らすこともできます(特に、リクエストでフィルタリングと並べ替えを使用しない場合)。
ネストされたフラグメントをフィルターまたは並べ替える場合でも、AEM は大量のフラグメントをメモリに読み込む必要があるので、ページ分割されたクエリの処理に時間がかかる場合があります。 したがって、フィルタリングとページングを組み合わせる場合は、(前述のように)フィルタリングのルールを考慮してください。
ページングの場合、ページ分割された結果が常に明示的または暗黙的に並べ替えられるので、並べ替えも同様に重要です。
最初の数ページのみを取得したい場合、...List
クエリと ...Paginated
クエリの使用に大きな違いはありません。 ただし、アプリケーションで 1~2 ページ以上のページを読みたい場合は、...Paginated
クエリを使用することをお勧めします。後のページで、パフォーマンスが著しく向上します。
ネストされたフラグメントをフィルタリングする場合でも、JCR フィルタリングを活用できます。AND
演算子を使用して組み合わされた最上位フィールドに付随するフィルターを指定して行います。
一般的なユースケースは、最上位フラグメントの _path
フィールドでフィルターを使用してクエリの範囲を制限し、最上位またはネストされたフラグメント上の追加フィールドでフィルタリングすることです。
この場合、様々なフィルター式が AND
で組み合わされます。したがって、_path
のフィルターにより、初期の結果セットが効果的に制限されます。 最上位フィールドのその他すべてのフィルターも、AND
で組み合わせた場合を除き、初期結果セットを減らすのに役立ちます。
ネストされたフラグメントが含まれている場合、OR
で組み合わされたフィルター式を最適化できません。OR
式は、ネストされたフラグメントが含まれていない場合にのみ最適化できます。
複数行のテキストフィールド(html、markdown、plaintext、json)のフィールドは、JCR クエリでフィルタリングできません。これらのフィールドの内容をその場で計算する必要があるからです。
それでも複数行のテキストフィールドに対してフィルタリングする必要がある場合は、フィルター式を追加して、初期の結果セットのサイズを制限し、AND
と組み合わせることを検討してください。_path
フィールドに対してフィルタリングして範囲を制限することも、適切なアプローチです。
仮想フィールド(_
で始まるほとんどのフィールド)は、GraphQL クエリの実行中に計算されるので、JCR ベースのフィルタリングの範囲外です。
重要な例外は _path
フィールです。コンテンツが適切に構造化されている場合は、初期結果セットのサイズを効果的に削減するために使用できます(コンテンツ構造の使用を参照)。
JCR レベルでフィルター式を評価できない場合が他にもいくつかあります(したがって、最高のパフォーマンスを実現するには回避する必要があります)。
_sensitiveness
フィルターオプションを使用し、_sensitiveness
が 0.0
以外に設定されている Float
値の式をフィルタリングします。
_ignoreCase
フィルターオプションを使用して、String
値の式をフィルタリングします。
null
値のフィルタリング。
_apply: ALL_OR_EMPTY
を使用して配列をフィルタリングします。
_apply: INSTANCES
、_instances: 0
を使用して配列をフィルタリングします。
CONTAINS_NOT
演算子を使用して式をフィルタリングします。
NOT_AT
演算子を使用する Calendar
、Date
または Time
値の式をフィルタリングします。