Considering
- your structure looks like that
- you are using UnifiedSearch
The ISearchContent interface of UnifiedSearch contains two useful properties in your scenario
- SearchSection
- SearchSubsection
Consider you have a path like this
/returns/misc/yourstuff
When looking at Your Stuff as a unified search hit the SearchSection would be Returns and the SearchSubsection would be Misc
When looking at Misc hit the SearchSection would be Returns and the SearchSubsection would be null
or not exist on the hit.
This means
- The SearchSection is always the first node below the root unless your result is a first level node
- The SearchSubsection is always the first node below the SearchSection unless your result is a first or second level node
In your scenario the category pages would always be represented as SearchSections.
I'm unable to test this at the moment but something like this should get your started.
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();
== Edit below==
To customize the SearchSection using projections something similar to this should be implemented, assuming you want the SearchSection to always be the closest parent of type CategoryPage
.
To implement in your Find Initialization
// 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 extension method
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 "";
}
}
Or something like that, you'll figure it out :)