3

I have a search result component showing all the events. The requirement is to add a CheckList filter to filter the events that have their event date before 9AM and after 9AM.

How can I create a custom facet to achieve this extending ISimpleFacet?

2 Answers 2

1

I could be wrong but I don't think implementing ISimpleFacet is the way to go for your situation. If anyone knows how to do it that way, that would be a great other answer.

But to solve your issue, you could also create an extra (custom) field in the sxa index. That field could contain your logic and have a value indicating whether the event was before or after 9AM - if that are the only options a boolean would be sufficient.

I you don't know how to create such an extra field, google is your best friend. Search for ComputedIndexField and you will find code and config examples. The code is similar across the different Sitecore versions - the configuration will differ between versions and is also dependent on the search provider (solr, azure search).

Your code will be something like:

public class MyComputedField : IComputedIndexField
{
    public object ComputeFieldValue(IIndexable indexable)
    {
        return (....  < 9AM);
            
    }
}

Your config could look like this (example from 9.2 and Azure):

<sitecore>
    <contentSearch>
      <indexConfigurations search:require="azure">
        <defaultCloudIndexConfiguration>
          <documentOptions>
            <fields hint="raw:AddComputedIndexField">
               <field fieldName="eventdatenine" returnType="bool" type="....MyComputedField, ..."/>
            </fields>
          </documentOptions>
        </defaultCloudIndexConfiguration>
      </indexConfigurations>
    </contentsearch>
</sitecore>

You can use such a field in a facet (use the index field name in the facet definition). If you want to use a list facet, you'd better use a string field (and not a bool) and put the values you want to have in the facet list in the index. Those values will be used by the filter component for the display.

2
  • Thanks Pal I know how to create computed index just one query can i use the same directly in facet?And in search filter what will be displayed (usually field name gets displayed when we use the list facet with field name) Commented Dec 27, 2020 at 17:27
  • Added to the answer - put the values you want in the index (use a string field) as those will be used to display.
    – Gatogordo
    Commented Dec 27, 2020 at 18:34
1

Firstly you should create a computed field like that.

public class IsBeforeNineComputedField : IComputedIndexField
{
  public override object ComputeFieldValue(IIndexable indexable)
  {
     Item item = indexable as SitecoreIndexableItem;
     var db = item.Database;
     var isCoreDb = string.Compare(item.Database.Name, "core", StringComparison.OrdinalIgnoreCase) == 0;
     if (db == null || isCoreDb)
     {
        return false;
     }
     var nineOClock  = new TimeSpan(9, 0, 0)
     return ((DateTime)item.Fields["Created"].Value).TimeOfDay < nineOClock;
   }
}

The config

<sitecore>
<contentSearch>
  <indexConfigurations search:require="azure">
    <defaultCloudIndexConfiguration>
      <documentOptions>
        <fields hint="raw:AddComputedIndexField">
           <field fieldName="isbeforenine" returnType="bool" type="Your.Namespace.IsBeforeNineComputedField, Your.Dll.Name"/>
        </fields>
      </documentOptions>
    </defaultCloudIndexConfiguration>
  </indexConfigurations>
</contentsearch>

A couple of auxiliary classes

public class FilterSearchResultItem : SearchResultItem
{
    [IndexField("isbeforenine_b")]
    public virtual string IsBeforeNine { get; set; }

    [IndexField("_latestversion")]
    public bool IsLatestVersion { get; set; }
}

public class SearchResponse
{
    public List<FilterSearchResultItem> Results { get; set; }
    public FacetCategory FacetIsBeforeNine { get; set; }
}

And the main search method would be more like

public SearchResponse GetSearchResults()
{
    using (var context = ContentSearchManager.GetIndex("sitecore_web_index").CreateSearchContext())
    {
        var query = context.GetQueryable<FilterSearchResultItem>();
        //Set the search context and check if is the last version of the item
        query = query.Where(x => x.Paths.Contains(ID.Parse("{9CCE9D90-CF8F-4210-B503-5474D48B4928}")) && x.IsLatestVersion);

        FacetCategory facet = query.FacetOn(it => it.IsBeforeNine).GetFacets().Categories.FirstOrDefault(it => it.Name.Equals("isbeforenine"));
        SearchResults<FilterSearchResultItem> searchResults = query.GetResults();
        List<FilterSearchResultItem> resultList = searchResults.Select(x => x.Document).ToList();
        return new SearchResponse
        {
            Results = resultList,
            FacetIsBeforeNine = facet
        };
    }
}

I I'm doing pretty much like that in a solution using Sitecore 10.3 with SXA and JSS

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.