Searching on module content on pages in Sitecore

When developing search implementation for a Sitecore site, we usually do an index search on the internal _content field which is an accumulation of all the string fields on the current item. Often the pages have a lot of important data on module datasources as opposed to be on the context item itself. We also have reference fields on the context item which might warrant updating the search results based on the business importance of such data.

To ensure that your search functionality also takes into account this additional data while retrieving results, we added a couple of computed fields to account for this data.

    • ModuleContent – This computed field accesses the presentation of an item and finds the renderings with datasources on them. It then adds all the string content on these datasource items to the computed field.
    • ReferenceContent – This computed field accesses all the fields on the context item which are reference fields and iterates through the referenced items to add into the index, the string fields of all these referenced items.

Now, while we can create new computed fields, we could also append to _content, which will let the search code unchanged. Writing to the _content field from the computed index field code simply appends the data into the existing field, thus extending it.

public class ModuleContent : IComputedIndexField
    {
        public string FieldName { get; set; }
        public string ReturnType { get; set; }

        public object ComputeFieldValue(IIndexable indexable)
        {
            Item obj = indexable as SitecoreIndexableItem;
            if (obj?.Template == null)
                return null;

            if (obj.Paths.IsContentItem)
            {
                try
                {
                    LayoutDefinition layout = LayoutDefinition.Parse(LayoutField.GetFieldValue(obj.Fields["__Renderings"]));

                    if (layout.Devices != null && layout.Devices.Count > 0)
                    {
                        DeviceDefinition dev = (DeviceDefinition)layout.Devices[0];
                        ArrayList renderings = dev?.Renderings;
                        if (renderings != null)
                        {
                            IEnumerable renderingDefinitions = renderings.Cast();

                            foreach (RenderingDefinition renderingDefinition in renderingDefinitions)
                            {
                                if (renderingDefinition.ItemID != null)
                                {
                                    if (!string.IsNullOrWhiteSpace(renderingDefinition.Datasource))
                                    {
                                        Item datasource = SitecoreHelper.GetItemByID(renderingDefinition.Datasource);

                                        if (datasource != null)
                                        {
                                            return datasource.Fields.Where(f => !f.Name.StartsWith("__")
                                                && f.Name != IBase_Rendering_AssetsConstants.Rendering_ScriptsFieldName
                                                && f.Name != IBase_Rendering_AssetsConstants.Rendering_StylesheetsFieldName
                                                && (f.Type == "Single-Line Text" || f.Type == "Multi-Line Text" || f.Type == "Rich Text"))
                                                .Select(f => datasource.Fields[f.ID]?.Value).Where(v => !string.IsNullOrWhiteSpace(v));
                                        }
                                    }
                                }
                            }
                        }
                    }

                    return new List();
                }
                catch (Exception ex)
                {
                    Log.Error("Site.Project._classes.Computed_Fields.ModuleContent", ex, this);
                }
            }

            return string.Empty;
        }
    }

In the configuration, we include the computed field:


  
    
      
        
          
            
              Site.Domain._classes.Computed_Fields.ModuleContent,Site.Domain
            
          
        
      
    
  

In a similar manner, we could include the reference item string fields, except we would filter by link / list field tyes like Multilist / Treelist / Droptree / Droplink etc in the code, to get the guids, then items and then string fields on them, to include in the index for the current item.

When time comes for the search, we would simply do a free text index search on the _content field to get results.

Hope this helps!

4 thoughts on “Searching on module content on pages in Sitecore

  1. You really make it seem so easy with your presentation however I in finding this topic to be really one thing which I believe I’d never understand. It seems too complicated and extremely broad for me. I am having a look ahead in your next post, I will try to get the hold of it!

    Like

  2. I’m not certain the place you are getting your info, however great topic. I must spend a while learning more or figuring out more. Thanks for fantastic information I used to be in search of this information for my mission.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s