如何基于父页面创建 "category" Facet?

How can I create a "category" Facet based on the parent page?

我有一个页面层次结构,例如

- Root
   - Category 1
        - Page 1
        - Page 2
   - Category 2
        - Page 3

我想使用 Find 创建一个基于类别页面名称的过滤器。这是我到目前为止所得到的,我无法弄清楚的是第 4 行

var result = _searchClient.Search()
                  .For(query)
                  .Filter(x => x.Ancestors().Match(rootPageLink.ID.ToString()))
                  .FilterFacet("Categories", x => x.ParentLink) // This doesn't work
                  .HistogramFacetFor(x => x.Price, 100)
                  .Skip((pageNumber - 1) * pageSize)
                  .Take(pageSize)
                  .GetContentResult();

显然这不起作用,因为 Filter() 需要 Filter 作为第二个参数,但您可以看到我正在尝试做什么。它大致类似于 GROUP BY ParentLink 之类的 SQL 查询,然后显示

之类的信息

Category 1 (2 pages)
Category 2 (1 page)

考虑

  • 你的结构看起来像那样
  • 您正在使用 UnifiedSearch

UnifiedSearch 的 ISearchContent 接口在您的场景中包含两个有用的属性

  • 搜索部分
  • 搜索子部分

假设你有这样的路径

/returns/misc/yourstuff

当查看 Your Stuff 作为统一搜索时,点击 SearchSection 将是 ReturnsSearchSubsection 将是 Misc

当查看 Misc 时点击 SearchSection 将是 ReturnsSearchSubsectionnull 或不存在于命中。

这意味着

  • SearchSection 总是根下面的第一个节点除非你的结果是第一级节点
  • SearchSubsection 总是 SearchSection 下面的第一个节点除非你的结果是一级或二级节点

在您的方案中,类别页面将始终表示为 SearchSections。

我目前无法对此进行测试,但像这样的东西应该可以让你开始。

var result = _searchClient.Search()
                  .For(query)
                  .Filter(x => x.SearchSection.Exists())
                  .Filter(x => x.SearchSection.Match("yourcategorypage"))
                  .TermsFacetFor(x => x.SearchSection) // create facets if you like, fun stuff
                  //.FilterFacet("Categories", x => x.ParentLink) // This doesn't work
                  //.Filter(x => x.Ancestors().Match(rootPageLink.ID.ToString()))
                  .HistogramFacetFor(x => x.Price, 100)
                  .Skip((pageNumber - 1) * pageSize)
                  .Take(pageSize)
                  .GetContentResult();

== 下面编辑==

要使用投影自定义 SearchSection,应该实现与此类似的东西,假设您希望 SearchSection 始终是类型 CategoryPage 的最近父级。

在你的查找初始化中实现

// use the appropriate datatype if PageData isn't applicable, i.e. ArticlePage
SearchClient.Instance.Conventions.ForInstancesOf<PageData>()
    .ExcludeField(x => x.SearchSection()) // remove the default mapping
    .IncludeField(x => x.SearchSection(true)); // add your own mapping

SearchSection 扩展方法

public static class FieldExtensions
{
    public static string SearchSection<T>(this T page, bool overriding) where T : PageData
    {
        // we need to check if this page is a CategoryPage first
        if(page is CategoryPage) {
            return ""; // I assume nothing?
        }

        var ancestors = loader.GetAncestors(page.ContentLink).OfType<CategoryPage>();
        if(ancestors.any()){
            var closestCategoryPage = ancestors.First();
            return closestCategoryPage.whateverproperty;
        }

        // customs: nothing to declare
        return "";
    }
}

或者类似的东西,你会想出来的:)