日本語版
最新ニュース
企業

インデックス作成時にグローバルアセットサイトと言語を認識します

先日、マルチサイトのグローバル資産の検索に関する質問があり、サポートケースがありました。これはその調査の結果です。 このコードはそのまま提供されますが、フィードバックがある場合はお知らせください。 Episerver(optimizely)CMSで、 グローバル資産- グローバルアセットフォルダーに保存されている画像、ドキュメント、ブロックなど、特定のサイトまたは言語に結び付けられていません。 しかし、参照するコンテンツは通常です。 あなたは一般的な問題に気づいたかもしれません:検索を実装するとき サイトa、参照されている資産 のみ コンテンツによって サイトb それでも結果に表示され、その逆も同様です。それは多分私たちが望むものではないかもしれません。 あなたが持っているとしましょう: 使用されている資産 独占的に の上 サイトa、 または 資産 共有 間 サイトa そして サイトb。 ユーザーが検索するとき サイトa、関連する結果が必要です のみ そのサイトに対して、そのサイトのコンテンツが参照するグローバル資産を含む。同様に、資産が両方のサイト間で共有されている場合、両方の結果セットに表示されるはずです。 これをサポートするために、あなた インデックス作成プロセス グローバル資産を作成する必要があります どのサイトと言語を認識しています それらを参照してください。 これが方法です 使用している場合 UnifiedSearch、サイトIDと言語でのこのフィルタリングは通常、次のように箱から出して動作します。 * filteroncurrentsite()…

インデックス作成時にグローバルアセットサイトと言語を認識します

1751068595
2025-06-26 16:11:00

先日、マルチサイトのグローバル資産の検索に関する質問があり、サポートケースがありました。これはその調査の結果です。
このコードはそのまま提供されますが、フィードバックがある場合はお知らせください。

Episerver(optimizely)CMSで、 グローバル資産– グローバルアセットフォルダーに保存されている画像、ドキュメント、ブロックなど、特定のサイトまたは言語に結び付けられていません。
しかし、参照するコンテンツは通常です。

あなたは一般的な問題に気づいたかもしれません:
検索を実装するとき サイトa、参照されている資産 のみ コンテンツによって サイトb それでも結果に表示され、その逆も同様です。それは多分私たちが望むものではないかもしれません。

あなたが持っているとしましょう:

  • 使用されている資産 独占的に の上 サイトa、 または

  • 資産 共有サイトa そして サイトb

ユーザーが検索するとき サイトa、関連する結果が必要です のみ そのサイトに対して、そのサイトのコンテンツが参照するグローバル資産を含む。同様に、資産が両方のサイト間で共有されている場合、両方の結果セットに表示されるはずです。

これをサポートするために、あなた インデックス作成プロセス グローバル資産を作成する必要があります どのサイトと言語を認識しています それらを参照してください。

これが方法です

使用している場合 UnifiedSearch、サイトIDと言語でのこのフィルタリングは通常、次のように箱から出して動作します。

* filteroncurrentsite() / filterSite()
* filterforvisitor() / publidedinlanguage()

また、入力された検索の場合、これらのフィルターを簡単に適用できます。

初期化モジュールを更新します

これをグローバル資産で機能させるために、ビルトインフィールドを除外し、独自のロジックに置き換えることにより、SiteID()およびPublidedInlanguage()のデフォルトのインデックス作成動作をオーバーライドします。

SearchClient.Instance.Conventions.ForInstancesOf().ExcludeField(x => x.SiteId());
SearchClient.Instance.Conventions.ForInstancesOf().IncludeField(x => x.SiteId(true));
SearchClient.Instance.Conventions.ForInstancesOf().ExcludeField(x => x.PublishedInLanguage());
SearchClient.Instance.Conventions.ForInstancesOf().IncludeField(x => x.PublishedInLanguage(true));

拡張メソッド

静的クラスのカスタムロジックを定義して、どのクラスを決定しますか サイト そして 言語 特定のグローバル資産を参照してください。

using EPiServer.Find.Cms;
using EPiServer.Framework.Cache;
using EPiServer.ServiceLocation;
using EPiServer.Web;
using EPiServer.Find.Helpers;

public static class GlobalAssetsExtensions
{
    private static readonly Lazy _siteDefinitionResolver =
        new(() => ServiceLocator.Current.GetInstance());

    private static readonly Lazy _contentLoader =
        new(() => ServiceLocator.Current.GetInstance());

    private static readonly Lazy _contentRepository =
        new(() => ServiceLocator.Current.GetInstance());

    private static readonly Lazy _versionContentRepository =
        new(() => ServiceLocator.Current.GetInstance());

    private static readonly Lazy _objectCache =
        new(() => ServiceLocator.Current.GetInstance());

    private static readonly Lazy _contentCacheKeyCreator =
        new(() => ServiceLocator.Current.GetInstance());

    public static IEnumerable SiteId(this IContentMedia content, bool foobar)
    {        
        content.ValidateNotNullArgument(nameof(content));

        var siteDefinitionResolver = _siteDefinitionResolver.Value;
        var contentLoader = _contentLoader.Value;
        var contentRepository = _contentRepository.Value;
        var objectCache = _objectCache.Value;
        var contentCacheKeyCreator = _contentCacheKeyCreator.Value;

        if (siteDefinitionResolver.GetByContent(content.ContentLink, false) == null)
        {
            if (ContentReference.IsNullOrEmpty(content.ParentLink) ||
                !contentLoader.TryGet(content.ParentLink, out _))
            {
                return Enumerable.Empty();
            }

            if (contentLoader.GetAncestors(content.ContentLink)
                             .Any(x => x.ContentLink == ContentReference.GlobalBlockFolder))
            {
                var cacheKey = $"SiteIds:{content.ContentLink.ID}";
                var cachedSiteIds = objectCache.Get(cacheKey) as IEnumerable;
                if (cachedSiteIds != null)
                {
                    return cachedSiteIds;
                }

                var contentRefs = new HashSet();

                foreach (var link in contentRepository.GetReferencesToContent(content.ContentLink, false))
                {
                    if (!ContentReference.IsNullOrEmpty(link.OwnerID))
                    {
                        contentRefs.Add(link.OwnerID);
                    }
                }

                var siteIds = new HashSet();
                foreach (var contentRef in contentRefs)
                {
                    var site = siteDefinitionResolver.GetByContent(contentRef, false);
                    if (site != null)
                    {
                        siteIds.Add(site.Id.ToString());
                    }
                }

                objectCache.Insert(cacheKey, siteIds, new CacheEvictionPolicy(
                    TimeSpan.FromMinutes(120), CacheTimeoutType.Sliding,
                    [contentCacheKeyCreator.VersionKey]));

                return siteIds;
            }
        }

        return [content.SiteId()];
    }

    public static Dictionary PublishedInLanguage(this IContentMedia content, bool foobar)
    {
        content.ValidateNotNullArgument(nameof(content));

        if (ContentReference.IsNullOrEmpty(content?.ContentLink))
        {
            return null;
        }

        var contentLoader = _contentLoader.Value;
        var contentRepository = _contentRepository.Value;
        var versionRepository = _versionContentRepository.Value;
        var objectCache = _objectCache.Value;
        var contentCacheKeyCreator = _contentCacheKeyCreator.Value;

        if (contentLoader.GetAncestors(content.ContentLink)
                         .Any(x => x.ContentLink == ContentReference.GlobalBlockFolder))
        {
            // Should we need to check whether entire ancestor chain are resolvable?

            var cacheKey = $"Languages:{content.ContentLink.ID}";
            var cachedLanguages = objectCache.Get(cacheKey) as Dictionary;
            if (cachedLanguages != null)
            {
                return cachedLanguages;
            }

            var contentRefs = new HashSet();

            foreach (var link in contentRepository.GetReferencesToContent(content.ContentLink, false))
            {
                if (!ContentReference.IsNullOrEmpty(link.OwnerID))
                {
                    contentRefs.Add(link.OwnerID);
                }
            }

            var languages = new Dictionary(StringComparer.OrdinalIgnoreCase);

            foreach (var contentRef in contentRefs)
            {
                var publishedLanguages = versionRepository
                    .ListPublished(contentRef)
                    .Select(x => x.LanguageBranch);
                
                foreach (var lang in publishedLanguages)
                {
                    if (contentLoader.TryGet(contentRef, new LanguageSelector(lang), out var contentInLang))
                    {
                        var langStatus = contentInLang.PublishedInLanguage();
                        if (langStatus != null)
                        {
                            foreach (var kvp in langStatus)
                            {
                                languages.TryAdd(kvp.Key, kvp.Value);
                            }
                        }
                    }
                }
            }

            objectCache.Insert(cacheKey, languages, new CacheEvictionPolicy(
                TimeSpan.FromMinutes(120), CacheTimeoutType.Sliding,
                [contentCacheKeyCreator.VersionKey]));

            return languages;
        }

        return content.PublishedInLanguage();
    }
}

インデックスでどのように見えるか

さまざまなサイトや言語で参照されているグローバル資産を再インド化した後、このような濃縮メタデータが含まれるようになりました

"PublishedInLanguage": { "sv": { "StartPublish$$date": "2017-02-22T11:24:00Z" },
 "fi": { "StartPublish$$date": "2025-06-18T11:03:00Z" },
 "en": { "StartPublish$$date": "2012-10-04T11:53:00Z" },
 "en-GB": { "StartPublish$$date": "2025-05-21T06:24:00Z" } }, 
"SiteId": [ "site-a-guid", "site-b-guid" ]

2025年6月26日

#インデックス作成時にグローバルアセットサイトと言語を認識します

執筆者について: nipponese

Nipponese News編集部は、国内外のニュースを日本語で分かりやすくお届けします。