1762182064
2025-11-03 10:23:00
私の別の記事へようこそ ヘッドレス化 シリーズ。以前に次のことについて説明しました。
これまで、アーキテクチャ上の決定、ページ上の編集、Optimizely Graph と他の API の比較について説明してきました。
今日は次のステップに進んで見ていきます。 Optimizely Graph でカスタム データを保存および公開する方法 — データは必ずしも CMS プロパティから直接取得されるわけではありません。
この記事では次のように説明します 3 つの異なるアプローチ:
- 規約 API の使用
- カスタムの作成 IContentApiModelProperty 実装
- グラフソースSDKの使用
各方法は、異なるレベルの制御、柔軟性、労力を提供します。飛び込んでみましょう。
Optimizely Graph でデータのインデックス付け方法に影響を与える最初の最も簡単な方法は、 規約API。この API を使用すると、開発者は CMS コンテンツがインデックス作成パイプラインに送信されるときに表現される方法を変更または拡張できます。つまり、コンテンツが Graph に公開される前に、Conventions API はデータを再形成または強化するためのフックを提供します。
いつ使用するか
次のことだけが必要な場合:
- 特定のプロパティまたはコンテンツ タイプを除外します。
- いくつかのカスタムフィールドを含めます。
- 既存のコンテンツ プロパティから派生した軽量メタデータを追加する
…その場合は、Conventions API があなたの親友です。
例:
あなたが持っているとしましょう ランディングページ そして 内部設定ページ コンテンツタイプ:
// InternalSettingsPage.cs
[ContentType(DisplayName = "Internal Settings Page")]
public class InternalSettingsPage : SitePageData
{
[Display(
Name = "Some Internal Setting",
Description = "A confidential value / setting that should not be published in Graph")]
public virtual string? SomeInternalSetting { get; set; }
}
// LandingPage.cs
using EPiServer.Core;
using EPiServer.DataAnnotations;
using System.ComponentModel.DataAnnotations;
[ContentType(DisplayName = "Landing Page")]
public class LandingPage : SitePageData
{
[Display(
Name = "Secret Property",
Description = "A confidential value not published in Graph")]
public virtual string? SecretProperty { get; set; }
[Display(
Name = "Title Prefix",
Description = "Prefix for the page title")]
public virtual string? TitlePrefix { get; set; }
[Display(
Name = "Title",
Description = "The main page title")]
public virtual string? Title { get; set; }
public virtual string PageTitle()
{
return TitlePrefix + " " + Title;
}
}
これらのコンテンツ タイプについては、次のことを行う必要があります。
- 除外する 内部設定ページ コンテンツ タイプがグラフにインデックス付けされないようにする
- を除外します。 SecretProperty Graph への漏洩を防ぐため、そして
- カスタムを含める ページタイトル グラフ インデックスのプロパティ (TitlePrefix プロパティと Title プロパティの組み合わせ)
簡単な規約登録でそれを行うことができます。
// GraphConventions.cs
using EPiServer.Framework;
using EPiServer.Framework.Initialization;
using EPiServer.ServiceLocation;
using Optimizely.ContentGraph.Cms.NetCore.ConventionsApi;
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class GraphConventions : IInitializableModule
{
public void Initialize(InitializationEngine context)
{
var conventionRepository = context.Locate.Advanced.GetInstance();
conventionRepository.ExcludeContentType();
conventionRepository.ForInstancesOf()
.ExcludeField(x => x.SecretProperty);
conventionRepository.ForInstancesOf()
.IncludeField(x => x.PageTitle());
}
public void Uninitialize(InitializationEngine context) { }
}
この規則が登録されると、Optimizely は除外されたコンテンツ タイプをスキップし、定義された調整を適用します。 LandingPage Graph でのインデックス作成のためにシリアル化されます。
場合によっては、慣例だけでは十分ではありません。
もしかしたら注射したいのかもしれない 動的データ それは CMS にはまったく存在しません。別のサービスからのデータ、または実行時の条件に依存する計算値です。
そのとき IContentApiModelProperty が登場します。
何をするのか
IContentApiModelProperty を定義できます 新しい物件 これは、Optimizely Graph でインデックス付けされるときに、すべてのコンテンツ アイテム (または選択したアイテム) で利用可能になります。
これは、カスタム データ、計算データ、または外部データをグラフ モデルに追加するためのプラグイン ポイントと考えることができます。
例: カスタム プロパティの追加
簡単な実装は次のとおりです。
using Optimizely.ContentGraph.Cms.Core.ContentApiModelProperties;
public sealed class CustomApiModelProperty : IContentApiModelProperty
{
private readonly IContentLoader _contentLoader;
public CustomApiModelProperty(IContentLoader contentLoader)
{
_contentLoader = contentLoader;
}
public string Name => "CustomPropertyName";
public object GetValue(ContentApiModel contentApiModel)
{
// Example: Load the content and derive a value dynamically
if (_contentLoader.TryGet(
new ContentReference(contentApiModel.ContentLink.Id ?? 0),
out SitePageData page))
{
return $"calculated-value-for-{page.Name}";
}
return null;
}
}
この物件を登録すると、 すべてのコンテンツ項目 Optimizely Graph に送信されるデータには、と呼ばれる追加フィールドが含まれます。 カスタムプロパティ名、 返される値が何であっても GetValue()。
たとえば、グラフ出力は次のようになります。
{
"name": "About Us",
"customPropertyName": "calculated-value-for-About Us"
}
実用的な用途
- 外部 API からのコンテンツの挿入 (たとえば、商品ページの在庫データの取得)
- 派生値の計算 (読書時間、評価平均など)
- 環境またはコンテキストメタデータの追加
最後のアプローチは最も柔軟で、CMS から最も分離されています。
データをお持ちであれば 完全に外部の CMS (CRM、ERP、カスタム データベースなどから) に接続するには、 Optimizely Graph ソース SDK グラフに直接プッシュします。
SDK を使用すると、Optimizely Graph に公開する内容と方法を完全に制御でき、 カスタムスキーマ そして データを手動で入力する。
いつ使用するか
次の場合に SDK を使用します。
- 非 CMS データ (製品カタログ、イベント、ユーザー プロファイルなど) のインデックスを作成する必要がある
- サードパーティのデータ ソースを Graph と同期したい
- CMS が複数のコンテンツ ソースの 1 つにすぎないヘッドレス アーキテクチャを構築しています。
例: 外部データのプッシュ
以下は、に基づいた簡略化された例です。 GitHub 上のグラフ ソース SDK:
using Optimizely.Graph.Source.Sdk;
using Optimizely.Graph.Source.Sdk.SourceConfiguration;
public class ExternalProduct
{
public string? Id { get; set; }
public string? Name { get; set; }
public double Price { get; set; }
}
// Initialize the GraphSourceClient by calling the Create method
var source = "custom-source";
var appKey = "your-app-key";
var secret = "your-secret";
// Initialize the GraphSourceClient by calling the Create method
var client = GraphSourceClient.Create(new Uri("https://cg.optimizely.com"), source, appKey, secret);
// Add a language preference
client.AddLanguage("en");
// Configure content type for ExternalProduct
client.ConfigureContentType()
.Field(x => x.Id, IndexingType.Searchable)
.Field(x => x.Name, IndexingType.Searchable)
.Field(x => x.Price, IndexingType.Queryable);
// Save content types to Optimizely Graph
client.SaveTypesAsync();
// Instantiate and assign values for ExternalProduct
var product = new ExternalProduct
{
Id = "SKU-001",
Name = "Custom Running Shoes",
Price = 129.99,
};
// Use the client to sync the product
client.SaveContentAsync(generateId: (x) => x.Id, "en", product);
このコードはカスタム スキーマを定義します (社外品) そしてそれを Optimizely Graph に公開します。
インデックスが作成されると、CMS コンテンツと同様に、GraphQL を通じてデータを直接クエリできます。
Optimizely Graph ソースに関する重要な注意事項:
上記のコードでは、ソースを次のように指定しました。 カスタムソース、 ただし、データ ソースを論理的に分離するために任意の名前を選択できます。それぞれ ソース Optimizely Graph 内で独自のコンテナとして機能します。
デフォルトでは、CMS コンテンツは次の場所に保存されます。 デフォルト ソース。もし使うとしたら デフォルト カスタム タイプをプッシュするときにソースとして使用すると、そのソースのグラフ スキーマ全体が上書きされる危険があります。これは電話をかけているからです client.SaveTypesAsync() ターゲット ソース内のすべてのコンテンツ タイプを、によって指定されたコンテンツ タイプのみに置き換えます。 コンテンツタイプを構成します。
CMS データとスキーマの中断を避けるために、外部データは常に別のソース名 (例: カスタムソース)。 これにより、外部型が隔離され、意図しない変更から安全に保たれます。
クエリの例
query CustomQuery {
ExternalProduct {
items {
Id
Name
Price
}
}
}
そして、次のものが得られます:
{
"data": {
"ExternalProduct": {
"items": [
{
"Id": "SKU-001",
"Name": "Custom Running Shoes",
"Price": 129.99
}
]
}
},
"extensions": {
"correlationId": "998b0a360df95906",
"cost": 23,
"costSummary": [
"ExternalProduct(23) = limit(20) + 3*fields(1)"
]
}
}
重要なポイント
次の場合にグラフ ソース SDK を使用します。
- データは CMS の外部に存在します。
- スキーマを完全に制御したい場合は、
- Graph をより大きなヘッドレス エコシステムの一部として統合しています。
これは最も高度なオプションですが、同時に最大限の可能性も開きます。
ヘッドレス設定では、 グラフを最適化する 単なるコンテンツ配信レイヤー以上のものになります。
として機能できます 集中型データハブ — CMS コンテンツ、計算されたプロパティ、および外部データセットを 1 つの統合された GraphQL API で結合します。
要約すると:
| アプローチ | こんな方に最適 | 努力のレベル | 注意事項 |
|---|---|---|---|
| 規約API | 既存の CMS データの整形 | 🟢 低い | データの名前変更、除外、またはわずかな強化に最適 |
| IContentApiModelProperty | 動的データまたは計算されたデータの挿入 | 🟠中 | 計算フィールドまたは外部フィールドの追加に最適 |
| グラフソースSDK | 非 CMS データ ソースのインデックス作成 | 🔴高い | スキーマとインデックス作成を完全に制御 |
適切なアプローチの選択は、アーキテクチャ上の目標と、実際にどの程度「ヘッドレス」にしたいかによって異なります。
ほとんどのプロジェクトでは、次の組み合わせが最適に機能します。
- 使用 慣例 素早い調整のために、
- 追加 カスタムプロパティ 動的ロジックの場合、および
- で拡張します SDK 完全な制御が必要な場合。
今回の記事はここまでです ヘッドレス化!
次のパートでは、結合されたデータセットを効率的にクエリする方法と、実際のパフォーマンスに合わせてスキーマを設計する方法を見ていきます。
さらに読む
2025 年 11 月 3 日
#Optimizely #Graph #にカスタム #データを保存する #つの方法