Monday, October 17, 2022

Sitecore coveo create MultilistComputedField facet

Hi All,

Today we will discuss how we can create a multilist computed field facet. For that, assume a case where you have tagged industry as MultiList/Treelist/TreelistEx etc. In that scenario, you want to create a facet based on those tagged values. 
For that, I found a generic solution that is as below: 

First, you need to make an entry in a Coveo.SearchProvider.Custom.config file, but as per suggested by Sitecore, I also do not recommend the default configuration file for that, I made a separate config file. As per below:



<?xml version="1.0"?>
<configuration>
  <sitecore>
    <coveo>
      <defaultIndexConfiguration>
        <fieldMap>
          <fieldNames hint="raw:AddFieldByFieldName">
            <!-- This is an example of field.
                 Supported attributes, fieldName: The field name.
                                       isDisplayField: Whether or not the field should be displayed.
                                       isFacet: Whether or not the field is set as facet.
                                       isIncludedFreeText: Whether or not the field should be included in free text queries.
                                       isMultiValue: Whether or not the field should be indexed as a multiple value field.
                                       sortable: Whether or not the field is set as sortable.
                 For more information, see: https://developers.coveo.com/x/iocdAg -->

            <fieldType fieldName="ComputedIndustries" isFacet="true" isMultiValue="true" settingType="Coveo.Framework.Configuration.FieldConfiguration, Coveo.Framework" />

          </fieldNames>
        </fieldMap>
        <documentOptions>
          <fields hint="raw:AddComputedIndexField">

            <field fieldName="ComputedIndustries" primaryfield="RelatedIndustries" lookupfield="IndustryName">TestProject.Foundation.CoveoCustom.CustomField.MultilistComputedField, TestProject.Foundation.CoveoCustom</field>

          </fields>
        </documentOptions>
      </defaultIndexConfiguration>
    </coveo>
  </sitecore>
</configuration>

<field fieldName="ComputedIndustries" primaryfield="RelatedIndustries" lookupfield="IndustryName">TestProject.Foundation.CoveoCustom.CustomField.MultilistComputedField, TestProject.Foundation.CoveoCustom</field>
The above entry is called our custom generic class that creates a custom field.
And the entry below created the Multivalue facet. 
<fieldType fieldName="ComputedIndustries" isFacet="true" isMultiValue="true" settingType="Coveo.Framework.Configuration.FieldConfiguration, Coveo.Framework" />

Below code for made our field to Multivalue custom field:

using System.Collections.Generic;
using System.Linq;
using System.Xml;
using Sitecore.ContentSearch;
using Sitecore.ContentSearch.ComputedFields;
using Sitecore.Data;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;

namespace TestProject.Foundation.CoveoCustom.CustomField
{
    public class MultilistComputedField : IComputedIndexField
    {
        #region PrivateProtected
        //store xml configuration
        private readonly XmlNode m_Configuration;

        protected string GetConfigurationValue(string p_ConfigurationKey)
        {
            string configurationValue = null;
            if (m_Configuration != null && m_Configuration.Attributes != null)
            {
                XmlAttribute configurationAttribute = m_Configuration.Attributes[p_ConfigurationKey];
                if (configurationAttribute != null)
                {
                    configurationValue = configurationAttribute.Value;
                }
            }
            return configurationValue;
        }

        protected string PrimaryField
        {
            get
            {
                return GetConfigurationValue("primaryfield");
            }
        }

        protected string LookupField
        {
            get
            {
                return GetConfigurationValue("lookupfield");
            }
        }
        #endregion

        #region Properties
        /// <inheritdoc />
        public string FieldName { get; set; }
        /// <inheritdoc />
        public string ReturnType { get; set; }
        #endregion


        #region Public Methods

        public MultilistComputedField(XmlNode p_Configuration)
        {
            m_Configuration = p_Configuration;
        }

        /// <inheritdoc>
        public object ComputeFieldValue(IIndexable p_Indexable)
        {
            //get the primary field
            IIndexableDataField multivalueField = p_Indexable.GetFieldByName(PrimaryField);
            Item currentItem = (Item)(p_Indexable as SitecoreIndexableItem);
            //check for null
            if (multivalueField != null && currentItem != null)
            {
                string fieldValue = multivalueField.Value.ToString();
                //if the field has values
                if (!string.IsNullOrEmpty(fieldValue))
                {
                    List<string> guids = fieldValue.Split('|').ToList(); //split the fields using a pipe delimiter
                    List<string> returnVals = new List<string>();

                    //get the web database
                    Sitecore.Data.Database webDB = Sitecore.Configuration.Factory.GetDatabase("web");
                    foreach (string guid in guids)
                    {
                        //if we have a valid id, get the item
                        ID refID;
                        if (ID.TryParse(guid, out refID))
                        {
                            Item tempItem = webDB.GetItem(refID, currentItem.Language);
                            if (tempItem != null)
                            {
                                //if value is returned add it to the collection
                                returnVals.Add(tempItem.Fields[LookupField].ToString());
                            }
                        }
                        else //process it as text
                        {
                            Log.Warn(string.Format("Textbased Multivalue: Parent ID:{0} GUID:{1} Primary Field:{2} Lookup Field:{3}", p_Indexable.Id.ToString(), guid, PrimaryField, LookupField), this);
                            returnVals.Add(guid);
                        }
                    }
                    //return values with semi-colon delimited
                    return string.Join(";", returnVals);
                }
            }
            return null;
        }

        #endregion

    }
}
Reference:
https://docs.coveo.com/en/2623/coveo-for-sitecore-v5/using-out-of-the-box-computed-fields

I hope you enjoy this Sitecore blog. Stay tuned for more Sitecore related articles.

Till that happy Sitecoring :)


Please leave your comments or share this article if it’s useful for you.