コンテンツフラグメントと共に使用する AEM GraphQL API

Adobe Experience Manager(AEM)as a Cloud Service のコンテンツフラグメントを AEM GraphQL API と共に使用してヘッドレスコンテンツ配信を実現する方法を説明します。

コンテンツフラグメントと共に使用する AEM as a Cloud Service GraphQL API は、オープンソースの標準 GraphQL API に大きく依存しています。

AEM の GraphQL API を使用すると、ヘッドレス CMS 実装の JavaScript クライアントにコンテンツフラグメントを効率的に配信できます。

  • REST で API リクエストの反復を回避
  • 特定の要件に限定された配信を確保
  • 1 つの API クエリへの応答としてレンダリングに必要なものだけを一括配信
メモ

GraphQL は現在、Adobe Experience Manager(AEM)as a Cloud Service の、2 つの(個別の)シナリオで使用されています。

GraphQL API

GraphQL とは次のことを意味します。

  • …API のクエリ言語と、既存のデータを使用してこれらのクエリを満たすランタイムです。GraphQL は、API のデータの完全で理解可能な説明を提供し、必要なものを正確に要求する力をクライアントに与え、API の長期的な発展を促し、強力な開発ツールの実現を可能にします。

    GraphQL.org を参照

  • …柔軟な API レイヤー用のオープンな仕様。GraphQL を既存のバックエンドに重ね合わせて、以前に比べて迅速に製品を構築…。

    Explore GraphQL」を参照

  • 「…2012 年に Facebook 社内で開発されたデータクエリ言語および仕様です。その後、2015 年には公式にオープンソースとなりました。開発者の生産性を高め、転送データの量を最小限に抑えるために、REST ベースのアーキテクチャに代わる手段を提供します。GraphQL は、あらゆる規模の数百の組織により実稼働環境で使用されています…」

    GraphQL Foundation を参照してください。

GraphQL API について詳しくは、次の節(その他の多くのリソース)を参照してください。

AEM 用 GraphQL の実装は、標準の GraphQL Java ライブラリをベースにしています。以下を参照してください。

GraphQL 用語

GraphQL では次を使用します。

ベストプラクティスを含む包括的な詳細については、「(GraphQL.org) GraphQL の概要」を参照してください。

GraphQL クエリタイプ

GraphQL では、次のいずれかを返すクエリを実行できます。

AEM は、クエリ(両方のタイプ)を Dispatcher と CDN によってキャッシュできる永続クエリに変換する機能を提供します。

GraphQL クエリのベストプラクティス(Dispatcher と CDN)

永続クエリは、パブリッシュインスタンスで次のように使用することをお勧めします。

  • キャッシュされます
  • AEM as a Cloud Service で一元管理されます
メモ

通常、作成者には Dispatcher/CDN がないので、永続クエリをテストする以外に使用してもメリットはありません。

POST リクエストを使用する GraphQL クエリは、キャッシュされないのでお勧めしません。そのため、デフォルトのインスタンスでは、Dispatcher はそれらのクエリをブロックするように設定されています。

GraphQL は GET リクエストもサポートしていますが、永続クエリを使用して回避できる制限(URL の長さなど)に達する可能性があります。

詳しくは、 永続クエリのキャッシュの有効化 詳しくは、を参照してください。

メモ

Dispatcher での直接クエリや POST クエリを許可するには、システム管理者に次の操作を依頼してください。

メモ

直接クエリを実行する機能は、将来、廃止される可能性があります。

GraphiQL IDE

また、GraphiQL IDE を使用して、GraphQL クエリのテストとデバッグを行うこともできます。

オーサー、プレビュー、パブリッシュの使用例

使用例は、AEM as a Cloud Service 環境のタイプに応じて異なる場合があります。

  • パブリッシュ環境の使用目的:

    • JS アプリケーションのデータのクエリ(標準の使用例)
  • プレビュー環境。次の目的で使用します。

    • パブリッシュ環境にデプロイする前にクエリをプレビューします。
      • JS アプリケーションのデータのクエリ(標準の使用例)
  • オーサー環境の使用目的:

    • 「コンテンツ管理用」のデータのクエリ:
      • AEM as a Cloud Service の GraphQL は現在読み取り専用の API です。
      • REST API は、CR(U)D の操作に使用できます。

権限

Assets へのアクセスに必要な権限です。

GraphQL クエリは、基になるリクエストの AEM ユーザーの権限で実行します。一部のフラグメント(Assets として保存)への読み取りアクセス権を持っていない場合、ユーザーは結果セットの一部になりません。

また、ユーザーは GraphQL クエリを実行できるように、GraphQL エンドポイントにアクセスできる必要があります。

スキーマ生成

GraphQLは、厳密に型指定された API で、データは型別に明確に構造化および整理される必要があります。

GraphQL の仕様には、特定のインスタンス上のデータをクエリするための堅牢な API を作成する方法に関する一連のガイドラインが用意されています。そのタスクを行うには、クライアントはスキーマを取得する必要があります。この中には、クエリに必要なすべての型が定義されています。

コンテンツフラグメントの場合、GraphQL スキーマ(構造とタイプ)は、有効​なコンテンツフラグメントモデルとそれらのデータタイプに基づいています。

注意

有効​になっているコンテンツフラグメントモデルから派生した)すべての GraphQL スキーマは、GraphQL エンドポイントを通じて読み取り可能です。

つまり、漏洩するおそれがあるので、機密データが使用可能になっていないことを確認する必要があります。例えば、これには、モデル定義のフィールド名として存在する可能性のある情報が含まれます。

例えば、ユーザーが Article というコンテンツフラグメントモデルを作成した場合、AEM は GraphQL タイプ ArticleModel を生成します。このタイプに含まれるフィールドは、モデルで定義されているフィールドとデータタイプに対応しています。さらに、articleByPatharticleList など、このタイプで動作するクエリのいくつかのエントリポイントを作成します。

  1. コンテンツフラグメントモデル:

    GraphQL で使用するコンテンツフラグメントモデル
  2. 対応する GraphQL スキーマ(GraphiQL 自動生成ドキュメントからの出力):
    コンテンツフラグメントモデルに基づく GraphQL スキーマ

    この図では、生成された型 ArticleModel に複数のフィールドが含まれていることがわかります。

    • そのうちの 3 つ(authormainreferencearticle)は、ユーザーが管理しています。

    • その他のフィールドは AEM によって自動的に追加され、特定のコンテンツフラグメントに関する情報を提供するための便利な方法を表しています。この例では、(ヘルパーフィールド_path_metadata_variations です。

  3. ユーザーが Article モデルに基づいてコンテンツフラグメントを作成すると、GraphQL を使用してそれをクエリできます。例については、(GraphQL で使用するコンテンツフラグメント構造のサンプルに基づいた)サンプルクエリを参照してください。

AEM 用 GraphQL では、スキーマには柔軟性があります。つまり、コンテンツフラグメントモデルを作成、更新、削除するたびに、スキーマが自動生成されます。また、コンテンツフラグメントモデルを更新すると、データスキーマキャッシュも更新されます。

また、コンテンツフラグメントモデルを更新すると、データスキーマキャッシュも更新されます。

Sites GraphQL サービスは、コンテンツフラグメントモデルに対する変更を(バックグラウンドで)リッスンします。更新が検出されると、スキーマのその部分だけが再生成されます。この最適化により、時間が節約され、安定性も確保されます。

例えば、次のようになります。

  1. Content-Fragment-Model-1Content-Fragment-Model-2 を含んだパッケージをインストールすると、

    1. Model-1 および Model-2 の GraphQL タイプが生成されます。
  2. 次に Content-Fragment-Model-2 を変更すると、

    1. Model-2 GraphQL 型だけが更新されます。

    2. 一方、Model-1 は同じままです。

メモ

REST API を使用してコンテンツフラグメントモデルの一括更新を行う場合などには、この点に留意することが大切です。

スキーマは、GraphQL クエリと同じエンドポイントを通じて提供され、クライアントはスキーマが拡張子 GQLschema で呼び出されることに対処します。例えば、/content/cq:graphql/global/endpoint.GQLschema で単純な GET リクエストを実行すると、text/x-graphql-schema;charset=iso-8859-1 の Content-type を持つスキーマが出力されます。

スキーマの生成 - 未公開のモデル

コンテンツフラグメントがネストされると、親のコンテンツフラグメントモデルは公開されますが、参照モデルは公開されません。

メモ

AEM UI はこのような問題を回避しますが、プログラムを使用して、またはコンテンツパッケージを使用して公開すると、この問題が発生する可能性があります。

この場合、AEM は親コンテンツフラグメントモデルの​不完全な​スキーマを生成します。つまり、非公開のモデルに依存するフラグメント参照がスキーマから削除されます。

フィールド

スキーマ内には、次の 2 つの基本的なカテゴリに属する個々のフィールドがあります。

  • ユーザーが生成するフィールド

    選択されたフィールドタイプを使用して、コンテンツフラグメントモデルの設定方法に基づいてフィールドが作成されます。フィールド名は、「データタイプ」タブの「プロパティ名」フィールドから取得されます。

    • ユーザーが特定のデータタイプを設定できるので、レンダリング形式​設定も考慮する必要があります。例えば、1 行のテキストフィールドに複数の 1 行のテキストを含めるように設定するには、ドロップダウンから「multifield」を選択します。
  • AEM 用 GraphQL が生成する多数のヘルパーフィールド

データタイプ

AEM 用 GraphQL では一連のタイプをサポートしています。サポートされているすべてのコンテンツフラグメントモデルデータ型と、それに対応する GraphQL 型を以下の表に示します。

コンテンツフラグメントモデル - データ型 GraphQL の型 説明
1 行のテキスト String[String] 作成者名、場所名などの単純な文字列に使用します.
複数行テキスト String[String] 記事の本文などのテキストを出力するために使用します
数値 Float[Float] 浮動小数点数と整数を表示するために使用します
ブール値 Boolean チェックボックスを表示するために使用します(単純な真/偽のステートメント)
日時 Calendar 日時を ISO 8601 形式で表示するために使用します. 選択したタイプに応じて、AEM GraphQL で使用できるフレーバーは、onlyDateonlyTimedateTime の 3 つです。
定義済みリスト String モデルの作成時に定義されたオプションのリストに含まれるオプションを表示するために使用します
タグ [String] AEM で使用されているタグを表す文字列のリストを表示するために使用します
コンテンツ参照 String[String] AEM 内の別のアセットへのパスを表示するために使用します
フラグメント参照 モデルタイプ

単一のフィールド: Model - 直接参照されるモデル型

マルチフィールド(1 つの参照タイプ):[Model] - 型の配列 Model(配列から直接参照)

複数の参照型を持つマルチフィールド:[AllFragmentModels] - 和集合型を持つ配列から参照される、すべてのモデル型の配列
モデルの作成時に定義された、特定のモデル型の 1 つ以上のコンテンツフラグメントの参照に使用します

ヘルパーフィールド

GraphQL for AEMでは、ユーザー生成フィールドのデータタイプに加えて、 ヘルパー コンテンツフラグメントの識別に役立つフィールド、またはコンテンツフラグメントに関する追加情報の提供に役立つフィールドです。

これらのヘルパーフィールドは、ユーザーが定義したものと自動生成されたものを区別するために、先頭に _ が付きます。

パス

パスフィールドは、AEM GraphQL で識別子として使用され、AEM リポジトリ内のコンテンツフラグメントアセットのパスを表します。これをコンテンツフラグメントの識別子として選択した理由は次のとおりです。

  • AEM 内で一意である
  • 取得しやすい

次のコードでは、WKND チュートリアルで提供されているように、コンテンツフラグメントモデル Author に基づいて作成されたすべてのコンテンツフラグメントのパスを表示します。

{
  authorList {
    items {
      _path
    }
  }
}

特定のタイプのコンテンツフラグメントを 1 つ取得するには、まずそのパスも決定する必要があります。次に例を示します。

{
  authorByPath(_path: "/content/dam/wknd-shared/en/contributors/sofia-sj-berg") {
    item {
      _path
      firstName
      lastName
    }
  }
}

サンプルクエリ - ある 1 つの特定の都市フラグメントを参照してください。

メタデータ

また、AEM では GraphQL を通じて、コンテンツフラグメントのメタデータも公開します。メタデータは、コンテンツフラグメントのタイトル、サムネールパス、コンテンツフラグメントの説明、作成日など、コンテンツフラグメントを説明する情報です。

メタデータはスキーマエディターで生成され、特定の構造を持たないので、コンテンツフラグメントのメタデータを公開するために GraphQL 型 TypedMetaData が実装されました。TypedMetaData では、次のスカラー型でグループ化された情報を公開します。

フィールド
stringMetadata:[StringMetadata]!
stringArrayMetadata:[StringArrayMetadata]!
intMetadata:[IntMetadata]!
intArrayMetadata:[IntArrayMetadata]!
floatMetadata:[FloatMetadata]!
floatArrayMetadata:[FloatArrayMetadata]!
booleanMetadata:[BooleanMetadata]!
booleanArrayMetadata:[booleanArrayMetadata]!
calendarMetadata:[CalendarMetadata]!
calendarArrayMetadata:[CalendarArrayMetadata]!

各スカラー型は、名前と値の 1 つのペアを表すか、名前と値のペアの配列を表します。このペアの値は、グループ化されたときの型になります。

例えば、コンテンツフラグメントのタイトルを取得する場合は、このプロパティが String 型プロパティであることがわかっているので、すべての String 型メタデータをクエリすることになります。

メタデータをクエリするには、次のようにします。

{
  authorByPath(_path: "/content/dam/wknd-shared/en/contributors/sofia-sj-berg") {
    item {
      _metadata {
        stringMetadata {
          name
          value
        }
      }
    }
  }
}

生成された GraphQL スキーマを表示するには、すべてのメタデータ GraphQL 型を表示します。すべてのモデルタイプは同じ TypedMetaData を持ちます。

メモ

標準メタデータと配列メタデータの違い
StringMetadataStringArrayMetadata はどちらも、リポジトリに格納されているものについての指定であり、その取得手段についての指定ではありません。

例えば、stringMetadata フィールドを呼び出すと、リポジトリに String として格納されているすべてのメタデータの配列を受け取ることになります。一方、stringArrayMetadata を呼び出すと、リポジトリに String[] として格納されているすべてのメタデータの配列を受け取ります。

詳しくは、メタデータのサンプルクエリ - 「GB」という賞のメタデータのリストを参照してください。

バリエーション

コンテンツフラグメントのバリエーションに対するクエリを簡略化するために、_variations フィールドが実装されています。例:

{
  authorByPath(_path: "/content/dam/wknd-shared/en/contributors/ian-provo") {
    item {
      _variations
    }
  }
}
メモ

技術的には元のデータ(UI で​マスター​として参照される)は明示的なバリエーションとは見なされないので、「_variations」フィールドには master バリエーションが含まれません。

詳しくは、サンプルクエリ - 名前付きバリエーションを持つすべての都市を参照してください。

メモ

コンテンツフラグメントに指定されたバリエーションが存在しない場合は、元のデータ(プライマリバリエーション)が(フォールバック)デフォルトとして返されます。

GraphQL 変数

GraphQL では、クエリに変数を含めることができます。詳細情報は、変数に関する GraphQL のドキュメントを参照してください。

例えば、特定のバリエーション(利用可能な場合)でタイプ Author のコンテンツフラグメントをすべて取得するには、GraphiQL で引数 variation を指定できます。

GraphQL 変数

クエリ

query($variation: String!) {
  authorList(variation: $variation) {
    items {
      _variation
      lastName
      firstName
    }
  }
}

クエリ変数

{
  "variation": "another"
}

このクエリは、作成者の完全なリストを返します。another バリエーションのない作成者は、元のデータに戻ります(この場合、_variationmaster をレポートします)。

適用: フィルター指定したバリエーションを提供する作成者にリストを制限する場合(および元のデータにフォールバックする作成者をスキップする場合):

query($variation: String!) {
  authorList(variation: $variation, filter: {
    _variation: {
      _expressions: {
        value: $variation
      }
    }
  }) {
    items {
      _variation
      lastName
      firstName
    }
  }
}

GraphQL ディレクティブ

GraphQL では、GraphQL ディレクティブと呼ばれる変数に基づいてクエリを変更する可能性があります。

例えば、 adventurePrice すべての AdventureModels(変数に基づく) includePrice.

GraphQL ディレクティブ

クエリ

query GetAdventureByType($includePrice: Boolean!) {
  adventureList {
    items {
      title
      price @include(if: $includePrice)
    }
  }
}

クエリ変数

{
    "includePrice": true
}

フィルタリング

GraphQL クエリでフィルタリングを使用して、特定のデータを返すこともできます。

フィルタリングでは、論理演算子と論理式に基づいた構文を使用します。

最もアトミックな部分は、特定のフィールドの内容に適用できる単一の式です。フィールドの内容を指定された定数値と比較します。

例えば、次の式

{
  value: "some text"
  _op: EQUALS
}

は、フィールドの内容を値 some text と比較し、内容が値と等しい場合に成功します。そうしないと、式は失敗します。

次の演算子を使用して、フィールドを特定の値と比較できます。

演算子 タイプ 次の場合、式は成功します
EQUALS StringIDBoolean … 値がフィールドの内容とまったく同じである
EQUALS_NOT StringID … 値がフィールドの内容と同じ​ではない
CONTAINS String … フィールドの内容に値が含まれる({ value: "mas", _op: CONTAINS }ChristmasXmasmaster などと一致)
CONTAINS_NOT String … フィールドの内容に値が含まれてい​ない
STARTS_WITH ID … ID が特定の値で始まる({ value: "/content/dam/", _op: STARTS_WITH/content/dam/path/to/fragment と一致するが、/namespace/content/dam/something とは一致しない)
EQUAL IntFloat … 値がフィールドの内容とまったく同じである
UNEQUAL IntFloat … 値がフィールドの内容と同じで​はない
GREATER IntFloat … フィールドの内容が値より大きい
GREATER_EQUAL IntFloat … フィールドの内容が値以上である
LOWER IntFloat … フィールドの内容が値よりも小さい
LOWER_EQUAL IntFloat … フィールドの内容が値以下である
AT CalendarDateTime … フィールドの内容が値とまったく同じである(タイムゾーン設定を含む)
NOT_AT CalendarDateTime … フィールドの内容が値と同じで​はない
BEFORE CalendarDateTime … 値によって示される時点が、フィールドの内容によって示される時点よりも前である
AT_OR_BEFORE CalendarDateTime … 値によって示される時点が、フィールドの内容によって示される時点より前または同じ時点である
AFTER CalendarDateTime … 値によって示される時点が、フィールドの内容によって示される時点よりも後である
AT_OR_AFTER CalendarDateTime … 値によって示される時点が、フィールドの内容によって示される時点より後または同じ時点である

また、式の評価方法を変更する追加のオプションを指定できるタイプもあります。

オプション タイプ 説明
_ignoreCase String 文字列の大文字と小文字は無視されます(例:time の値は TIMEtimetImE と一致)
_sensitiveness Float float 値が同じと見なされるための一定のマージンを許可します(float 値の内部表現による技術的な制限を回避するため)。このオプションはパフォーマンスに悪影響を及ぼす可能性があるので、避ける必要があります。

式は、論理演算子(_logOp)を使用して設定に組み合わせることができます。

  • OR - 少なくとも 1 つの式が成功した場合、式のセットは成功します
  • AND - すべての式が成功した場合、式のセットは成功します(デフォルト)

各フィールドは、独自の式セットでフィルタリングできます。 フィルター引数で指定されたすべてのフィールドの式セットは、最終的に独自の論理演算子で結合されます。

フィルター定義(filter 引数としてクエリに渡される)には次が含まれます。

  • 各フィールドのサブ定義(フィールド名を使用してアクセスできます。例えば、データ(フィールド)タイプの lastName フィールドのフィルターには lastName フィールドがあります)
  • 各サブ定義には、式セットを提供する _expressions 配列と、式を組み合わせる必要がある論理演算子を定義する _logOp フィールドが含まれます
  • 各式は、値(value フィールド)と演算子(_operator フィールド)によって定義され、フィールドの内容を比較する必要があります

項目を AND で組み合わせたい場合は _logOp を省略できます。また、等価性を確認したい場合は、これらがデフォルト値になるので、_operator を省略できます。

次の例は、大文字と小文字を区別せずに、ProvolastName である、または sjö を含むすべてのユーザーをフィルタリングする完全なクエリを示しています。

{
  authorList(filter: {
    lastname: {
      _logOp: OR
      _expressions: [
        {
          value: "sjö",
          _operator: CONTAINS,
          _ignoreCase: true
        },
        {
          value: "Provo"
        }
      ]
    }
  }) {
    items {
      lastName
      firstName
    }
  }
}

ネストされたフィールドに対してフィルターを適用することもできますが、パフォーマンスの問題が発生する可能性があるため、お勧めしません。

その他の例については、以下を参照してください。

並べ替え

メモ

この機能を使用すると、指定したフィールドに従ってクエリ結果を並べ替えることができます。

並び替え条件:

  • フィールドパスを表すコンマ区切りの値のリストにする
    • リストの最初のフィールドでは主な並べ替え順が定義され、2 番目のフィールドは主な並べ替え条件の 2 つの値が等しい場合に使用され、3 番目のフィールドは最初の 2 つの条件が等しい場合に使用されます。
    • ドット表記、つまり field1.subfield.subfield など
  • (オプション)並べ替えの方向
    • ASC(昇順)または DESC(降順)。デフォルトでは ASC が適用されます
    • 並べ替えの方向は、フィールドごとに指定できます。つまり、あるフィールドを昇順で、別のフィールドを降順(name、firstName DESC)で並べ替えることができます

次に例を示します。

query {
  authorList(sort: "lastName, firstName") {
    items {
      firstName
      lastName
    }
  }
}

次のようにすることもできます。

{
  authorList(sort: "lastName DESC, firstName DESC") {
    items {
        lastName
        firstName
    }
  }
}

また、nestedFragmentname.fieldname の形式を使用して、ネストされたフラグメント内のフィールドで並べ替えることもできます。

メモ

これは、パフォーマンスに悪影響を及ぼす可能性があります。

次に例を示します。

query {
  articleList(sort: "authorFragment.lastName")  {
    items {
      title
      authorFragment {
        firstName
        lastName
        birthDay
      }
      slug
    }
  }
}

ページング

メモ

この機能を使用すると、リストを返すクエリタイプに対してページングを実行できます。 次の 2 つの方法があります。

  • List クエリの offsetlimit
  • Paginated クエリの firstafter

リストクエリ - オフセットと制限

...List クエリでは、offsetlimit を使用して、特定の結果サブセットを返すことができます。

  • offset:返される最初のデータセットを指定します
  • limit:返されるデータセットの最大数を指定します

例えば、完全な​結果リストの 5 番目の記事から開始して、最大 5 つの記事を含む結果のページを出力するには、次のようにします。

query {
   articleList(offset: 5, limit: 5) {
    items {
      authorFragment {
        lastName
        firstName
      }
    }
  }
}
メモ
  • ページングには安定した並べ替え順序が必要です。同じ結果セットの異なるページをリクエストする複数のクエリで正しく動作するようにします。デフォルトでは、結果セットの各アイテムのリポジトリパスを使用して、順序が常に同じであることを確認します。 異なる並べ替え順を使用し、その並べ替えを JCR クエリレベルで実行できない場合は、ページを判断する前に結果セット全体をメモリに読み込む必要があるので、パフォーマンスに悪影響があります。

  • オフセットが大きいほど、JCR クエリの結果セット全体から項目をスキップするのに時間がかかります。 大規模な結果セットに対する代替ソリューションは、first および after メソッドでページ分割されたクエリを使用することです。

ページ分割されたクエリ - first と after

...Paginated クエリタイプは、ほとんどの ...List クエリタイプの機能(フィルタリング、並べ替え)を再利用しますが、offsetlimit 引数の代わりに、GraphQL カーソル接続仕様で定義されている firstafter 引数を使用します。GraphQL の概要では、堅苦しくない概要を見つけることができます。

  • first:返される最初の n 個の項目。
    デフォルトは、50 です。
    最大値は 100 です。
  • after:リクエストされたページの先頭を決定するカーソル。カーソルで表される項目は結果セットに含まれないことに注意してください。項目のカーソルは、edges 構造体の cursor フィールドによって決定されます。

例えば、完全な​結果リスト内の指定されたカーソル項目から開始して、最大 5 つの冒険を含む結果のページを出力します。

query {
    adventurePaginated(first: 5, after: "ODg1MmMyMmEtZTAzMy00MTNjLThiMzMtZGQyMzY5ZTNjN2M1") {
        edges {
          cursor
          node {
            title
          }
        }
        pageInfo {
          endCursor
          hasNextPage
        }
    }
}
メモ
  • デフォルトのページングでは、結果の順序が常に同じになるように、フラグメントを表すリポジトリノードの UUID を順序付けに使用します。sort を使用すると、UUID は一意の並べ替えを保証するために暗黙的に使用されます。同じ並べ替えキーを持つ 2 つの項目の場合も同様です。

  • 内部の技術的な制約により、ネストされたフィールドに並べ替えとフィルタリングを適用すると、パフォーマンスが低下します。したがって、ルートレベルで保存されたフィールドのフィルター/並べ替えを使用することをお勧めします。 これは、ページ分割された大きな結果セットをクエリする場合にも推奨される方法です。

GraphQL クエリでの Web に最適化された画像配信

Web に最適化された画像配信では、Graphql クエリを使用して次のことをおこなえます。

  • AEM Asset 画像に URL をリクエストする

  • 画像の特定のレンディションが自動的に生成されて返されるように、クエリでパラメーターを渡す

    メモ

    指定されたレンディションは AEM Assets に保存されません。レンディションは生成され、短期間キャッシュに保持されます。

  • JSON 配信の一部として URL を返す

AEM を使用して、次のことができます。

つまり、クエリの実行中に、これらの画像に対する GET リクエストの URL パラメーターと同じ方法でコマンドが適用されます。

これにより、JSON 配信の画像レンディションを動的に作成できるので、これらのレンディションを手動で作成してリポジトリに保存する必要がなくなります。

GraphQL のソリューションでは、次のことが可能です。

  • ImageRef 参照で _dynamicUrl を使用する

  • フィルターが定義されているリストヘッダーに _assetTransform を追加する

変換リクエストの構造

AssetTransform_assetTransform)は、URL 変換リクエストの作成に使用されます。

構造と構文は次のとおりです。

  • format:拡張子でサポートされるすべての形式を持つ列挙(GIF、PNG、PNG8、JPG、PJPG、BJPG、WEBP、WEBPLL、WEBPLY)
  • seoName:ノード名の代わりにファイル名として使用される文字列
  • crop:フレームサブ構造。幅または高さが省略された場合、高さまたは幅が同じ値として使用されます
    • xOrigin:フレームの x 原点(必須)
    • yOrigin:フレームの y 原点(必須)
    • width:フレームの幅
    • height:フレームの高さ
  • size:寸法サブ構造。幅または高さが省略された場合、高さまたは幅が同じ値として使用されます
    • width:寸法の幅
    • height:寸法の高さ
  • rotation:サポートされているすべての回転の列挙(R90、R180、R270)
  • flip:HORIZONTAL、VERTICAL、HORIZONTAL_AND_VERTICAL の列挙
  • quality:画質の割合を示す 1 ~ 100 の整数
  • width:出力画像の幅を定義する整数。ただし、Image Generator では無視されます。
  • preferWebp:webp が優先されるかどうかを示すブール値(デフォルト値は false)

URL 変換は、パス別、リスト別またはページ分割別のすべてのクエリタイプで使用できます。

すべてのパラメーターを使用した web に最適化された画像配信

すべてのパラメーターを使用したクエリ例を次に示します。

{
  articleList(
    _assetTransform: {
      format:GIF
      seoName:"test"
      crop:{
        xOrigin:10
        yOrigin:20
        width:50
        height:45
      }
      size:{
        height:100
        width:200
      }
      rotation:R90
      flip:HORIZONTAL_AND_VERTICAL
      quality:55
      width:123
      preferWebp:true
    }
  ) {
    items {
      _path
      featuredImage {
        ... on ImageRef {
          _dynamicUrl
        }
      }
    }
  }
}

単一のクエリ変数を使用した web に最適化された画像配信

単一のクエリ変数を使用した例を次に示します。

query ($seoName: String!) {
  articleList(
    _assetTransform: {
      format:GIF
      seoName:$seoName
      crop:{
        xOrigin:10
        yOrigin:20
        width:50
        height:45
      }
      size:{
        height:100
        width:200
      }
      rotation:R90
      flip:HORIZONTAL_AND_VERTICAL
      quality:55
      width:123
      preferWebp:true
    }
  ) {
    items {
      _path
      featuredImage {
        ... on ImageRef {
          _dynamicUrl
        }
      }
    }
  }
}

複数のクエリ変数を使用した web に最適化された画像配信

複数のクエリ変数を使用した例を次に示します。

query ($seoName: String!, $format: AssetTransformFormat!) {
  articleList(
    _assetTransform: {
      format:$format
      seoName:$seoName
      crop:{
        xOrigin:10
        yOrigin:20
        width:50
        height:45
      }
      size:{
        height:100
        width:200
      }
      rotation:R90
      flip:HORIZONTAL_AND_VERTICAL
      quality:55
      width:123
      preferWebp:true
    }
  ) {
    items {
      _path
      featuredImage {
        ... on ImageRef {
          _dynamicUrl
        }
      }
    }
  }
}

URL による web に最適化された画像配信リクエスト

クエリを永続化クエリとして保存した場合(例えば dynamic-url-x という名前を使用)、永続化クエリを直接実行できます。

例えば、以前のサンプル(永続化されたクエリとして保存)を直接実行するには、次の URL を使用します。

  • 単一のパラメーターdynamic-url-x という名前の永続クエリ

    • http://localhost:4502/graphql/execute.json/wknd-shared/dynamic-url-x;seoName=xxx

      応答は次のようになります。

      パラメーターを使用した画像配信
  • 複数のパラメーターdynamic という名前の永続クエリ

    • http://localhost:4502/graphql/execute.json/wknd-shared/dynamic;seoName=billiboy;format=GIF;

      注意

      末尾の ; は、パラメーターのリストを明確に終了するために必須です。

画像配信の制限

次の制限があります。

  • クエリのすべての画像部分に適用される修飾子(グローバルパラメーター)

  • ヘッダーのキャッシュ

    • オーサーにキャッシュされない
    • パブリッシュのキャッシュ - 10 分の最大経過時間(クライアントは変更できません)

AEM 用の GraphQL - 拡張機能の概要

AEM 用の GraphQL でのクエリの基本操作は、標準の GraphQL 仕様に従います。AEM での GraphQL クエリには、次のような拡張機能があります。

外部 web サイトからの GraphQL エンドポイントのクエリ

外部 web サイトから GraphQL エンドポイントにアクセスするには、次の項目を設定する必要があります。

認証

コンテンツフラグメントに対するリモート AEM GraphQL クエリの認証を参照してください。

FAQ

次のような質問が寄せられました。

  1. Q:「AEM 用 GraphQL API と Query Builder API の違いは何ですか?

    • A:「AEM GraphQL API は JSON 出力の完全な制御が可能であり、コンテンツをクエリするための業界標準になっています。今後、AEM GraphQL API への投資が計画されています。

チュートリアル - AEM ヘッドレスと GraphQL をはじめる前に

実践的なチュートリアルを探している場合は、AEM ヘッドレスおよび GraphQL 入門をご覧ください。これは、AEM の GraphQL API を使用してコンテンツを構築および公開し、ヘッドレス CMS シナリオで外部アプリによって使用する方法を説明する包括的なチュートリアルです。

このページ