Posted 08/10/2014 by Akshay Sura
Computed fields are very useful, especially if you are implementing a multi-site / multi-lingual Sitecore solution. In some of the previous blog posts, we have covered foreign keys, auto suggestions and other important topics related to Coveo JS Framework.
In this post we will concentrate on multilist fields and how to create ONE generic unit of code that can handle either text or guids in the computed fields. Generally if you were to add a computed field, you need a piece of configuration as shown below and a class to perform the work needed to generate the output for the computed field.
YOURNAMESPACE.Business.Search.ComputedFields.CUSTOMFIELDComputedField,YOURNAMESPACE.Business
This gets very tedious as you are creating multiple fields that store a delimited list of text or guids in the raw. Here is a great solution to cut down on code but achieve the same functionality. First we need configuration where we can call the same class but pass in the values. Here is a sample piece of config:
YOURNAMESPACE.Business.Search.ComputedFields.MultilistComputedField, YOURNAMESPACE.Business
YOURNAMESPACE.Business.Search.ComputedFields.MultilistComputedField, YOURNAMESPACE.Business YOURNAMESPACES.Business.Search.ComputedFields.MultilistComputedField, YOURNAMESPACE.Business
As you can see, we are calling the same code to generate the computed field value but we are passing in additional parameters via the config to specify which fields we want processed. Now for some code! As with any other computed field, we need to create a class which inherits IComputedField. The difference is that we need to pull in the additional configuration. Checkout the code below:
namespace YOURNAMESPACE.Business.Search.ComputedFields { 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(Constants.Global.IndexFields.ComputedFieldPrimary); } } protected string LookupField { get { return GetConfigurationValue(Constants.Global.IndexFields.ComputedFieldLookup); } } #endregion #region Properties /// public string FieldName { get; set; } /// public string ReturnType { get; set; } #endregion #region Public Methods public MultilistComputedField(XmlNode p_Configuration) { m_Configuration = p_Configuration; } /// 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 guids = fieldValue.Split('|').ToList(); //split the fields using a pipe delimiter List returnVals = new List(); //get the master database Sitecore.Data.Database master = Sitecore.Configuration.Factory.GetDatabase("master"); foreach (string guid in guids) { //if we have a valid id, get the item ID refID; if (ID.TryParse(guid, out refID)) { Item tempItem = master.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 } }
The ComputedFieldValue method exists as in any other computed field implementation, the difference is the constructor that takes in the XmlNode and when the properties are called we extract the attributes. I hope this helps you with your computed fields, let me know if you have any questions or need additional information.