Creating a custom multi-valued refiner

31 Mar

In one of my previous posts I wrote about extending the content processing pipeline by developing a custom content enrichment service to modify the managed properties of the crawled items before they are added to the search index. This post is a kind of follow up on that.

Suppose sites can be tagged by one or more terms. Users are able to set and modify these terms.

On a page with a content search webpart and a refinement panel users can search content and use the refinement panel to find sites (also) tagged with these terms.

These terms are stored in a propertybag, added to the indexed properties keys and exposed by a managed property.
The propertybag values for three different sites are:

CE2_Propertybag_Values

To point some values out: The term ‘site02|..’ is used twice (at site 01 and site 02) and the term ‘site04|..’ is used once (at site 03).

The managed property is added to the refinement panel and configured to use the multi-value refinement item display template.

CE2_Original_ManagedProperty_In_RefinementPanel

As you can see in the above image the managed property containing the terms isn’t really multivalued, because of the values of the propertybag are stored as a single string. Notice the missing ‘site04|…’ in the refinementpanel, which is present in the propertybag shown in the PowerShell image. Creating the managed property as a multivalued property won’t help you create a real multivalued property.

A content search webpart in conjunction with this refinement panel will show only one site at the time when eg selecting ‘site02|..’ which is used twice and should result Site 01 and Site 02:

CE2_Original_ContentSearch

Refining results based on these values will only match sites when they are tagged with the same terms in the same order: the exact same string.

A possible solution for this is to extend the content processing pipeline by a service. This service picks up the propertybag value and splits the values, in this case the terms, and inserts the separate values into the multivalued managed property.

The basics of how to set up a custom content enrichment service is explained in the post ‘Issue sorting links and documents based on Title

Only the code for the service itself is shown. This is the service which accepts requests from the content processing component.

private const string
SiteTagProperty = "ITIdeaSiteTag";

private const int UnexpectedType = 1;
private const int UnexpectedError = 2;
private readonly ProcessedItem processedItemHolder = new ProcessedItem
{
    ItemProperties = new List<AbstractProperty>()
};

public ProcessedItem ProcessItem(Item item)
{
    processedItemHolder.ErrorCode = 0;
    processedItemHolder.ItemProperties.Clear();
    try
    {
        // Iterate over each property received and locate the property we configured the system to send.
        foreach (var property in item.ItemProperties)
        {
            if (property.Name.Equals(SiteTagProperty, StringComparison.Ordinal))
            {
                var siteTag = property as Property<List<string>>;
                if (siteTag != null && siteTag.Value != null && siteTag.Value.Count > 0)
                {
                    string[] propValues = siteTag.Value.First().Split(';');
                    List<string> listpropValues = propValues.ToList();
                    Property<List<string>> newSiteTagProp = new Property<List<string>>();
                    newSiteTagProp.Name = SiteTagProperty;
                    newSiteTagProp.Value = listpropValues;
                    processedItemHolder.ItemProperties.Add(newSiteTagProp);
                }
            }
        }
    }
    catch (Exception)
    {
        processedItemHolder.ErrorCode = UnexpectedError;
    }
    return processedItemHolder;
}

The item.ItemProperties contain all the input properties received by the service. These input properties will be configured by PowerShell.
The code checks if the ITIdeaSiteTag property contains multiple terms, splits it and adds it to a list of property values and returns the changed value to the content processing component.

Configure the Search Service Application to use the Content Enrichment service by using PowerShell, for an example see this post. Don’t forget to set a meaningful trigger otherwise every item will be passed this service.

Run a full crawl.

The refinement panel now shows a nice set of single values, notice the presence of ‘site04|..’ here:

CE2_Enriched_ManagedProperty_In_RefinementPanel

When using the refinement panel in conjunction with a content search webpart, two sites will be displayed when selecting e.g. ‘site02|..’ as expected:

CE2_Enriched_ContentSearch

 

Summary

To make a multivalued propertybag a real multivalued managed property a custom content enrichment service can de developed to accomplish this.
After creating a multivalued managed property it can be used in e.g. a refinement panel.

The intention of this post was purely to demonstrate the technique, no changes has been made to make things look pretty 🙂

Note

Only one custom content enrichment service can be bound to a Search Service Application.
If you want more properties to be processed by the service you have to configure the InputProperties, OutputProperties and don’t forget the Trigger of the EnterpriseSearchContentEnrichmentConfiguration object to handle them all.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.