{"id":1978,"date":"2015-03-31T23:08:55","date_gmt":"2015-03-31T21:08:55","guid":{"rendered":"http:\/\/www.itidea.nl\/?p=1978"},"modified":"2015-03-31T23:08:55","modified_gmt":"2015-03-31T21:08:55","slug":"creating-a-custom-multi-valued-refiner","status":"publish","type":"post","link":"https:\/\/www.itidea.nl\/index.php\/creating-a-custom-multi-valued-refiner\/","title":{"rendered":"Creating a custom multi-valued refiner"},"content":{"rendered":"<p>In one of my <a href=\"https:\/\/www.itidea.nl\/index.php\/issue-sorting-links-and-documents-based-on-title\/\">previous posts<\/a> 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.<\/p>\n<p>Suppose sites can be tagged by one or more terms. Users are able to set and modify these terms.<\/p>\n<p>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.<\/p>\n<p>These terms are stored in a propertybag, added to the indexed properties keys and exposed by a managed property.<br \/>\nThe propertybag values for three different sites are:<\/p>\n<p><a href=\"https:\/\/www.itidea.nl\/wp-content\/uploads\/2015\/03\/CE2_Propertybag_Values.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1979 size-full\" src=\"https:\/\/www.itidea.nl\/wp-content\/uploads\/2015\/03\/CE2_Propertybag_Values.png\" alt=\"CE2_Propertybag_Values\" width=\"716\" height=\"81\" srcset=\"https:\/\/www.itidea.nl\/wp-content\/uploads\/2015\/03\/CE2_Propertybag_Values.png 716w, https:\/\/www.itidea.nl\/wp-content\/uploads\/2015\/03\/CE2_Propertybag_Values-300x33.png 300w, https:\/\/www.itidea.nl\/wp-content\/uploads\/2015\/03\/CE2_Propertybag_Values-600x67.png 600w\" sizes=\"auto, (max-width: 716px) 100vw, 716px\" \/><\/a><\/p>\n<p>To point some values out: The term &#8216;site02|..&#8217; is used twice (at site 01 and site 02) and the term &#8216;site04|..&#8217; is used once (at site 03).<\/p>\n<p>The managed property is added to the refinement panel and configured to use the multi-value refinement item display template.<\/p>\n<p><a href=\"https:\/\/www.itidea.nl\/wp-content\/uploads\/2015\/03\/CE2_Original_ManagedProperty_In_RefinementPanel.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1980 size-full\" src=\"https:\/\/www.itidea.nl\/wp-content\/uploads\/2015\/03\/CE2_Original_ManagedProperty_In_RefinementPanel.png\" alt=\"CE2_Original_ManagedProperty_In_RefinementPanel\" width=\"201\" height=\"251\" \/><\/a><\/p>\n<p>As you can see in the above image the managed property containing the terms isn&#8217;t really multivalued, because of the values of the propertybag are stored as a single string. Notice the missing &#8216;site04|&#8230;&#8217; in the refinementpanel, which is present in the propertybag shown in the PowerShell image. Creating the managed property as a multivalued property won&#8217;t help you create a real multivalued property.<\/p>\n<p>A content search webpart in conjunction with this refinement panel will show only one site at the time when eg selecting &#8216;site02|..&#8217; which is used twice and should result Site 01 and Site 02:<\/p>\n<p><a href=\"https:\/\/www.itidea.nl\/wp-content\/uploads\/2015\/03\/CE2_Original_ContentSearch.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1983 size-full\" src=\"https:\/\/www.itidea.nl\/wp-content\/uploads\/2015\/03\/CE2_Original_ContentSearch.png\" alt=\"CE2_Original_ContentSearch\" width=\"183\" height=\"297\" \/><\/a><\/p>\n<p>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.<\/p>\n<p>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.<\/p>\n<p>The basics of how to set up a custom content enrichment service is explained in the post &#8216;<a href=\"https:\/\/www.itidea.nl\/index.php\/issue-sorting-links-and-documents-based-on-title\/\">Issue sorting links and documents based on Title<\/a>&#8216;<\/p>\n<p>Only the code for the service itself is shown. This is the service which accepts requests from the content processing component.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nprivate const string\r\nSiteTagProperty = &quot;ITIdeaSiteTag&quot;;\r\n\r\nprivate const int UnexpectedType = 1;\r\nprivate const int UnexpectedError = 2;\r\nprivate readonly ProcessedItem processedItemHolder = new ProcessedItem\r\n{\r\n\u00a0\u00a0\u00a0 ItemProperties = new List&lt;AbstractProperty&gt;()\r\n};\r\n\r\npublic ProcessedItem ProcessItem(Item item)\r\n{\r\n\u00a0\u00a0\u00a0 processedItemHolder.ErrorCode = 0;\r\n\u00a0\u00a0\u00a0 processedItemHolder.ItemProperties.Clear();\r\n\u00a0\u00a0\u00a0 try\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Iterate over each property received and locate the property we configured the system to send.\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 foreach (var property in item.ItemProperties)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (property.Name.Equals(SiteTagProperty, StringComparison.Ordinal))\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var siteTag = property as Property&lt;List&lt;string&gt;&gt;;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (siteTag != null &amp;&amp; siteTag.Value != null &amp;&amp; siteTag.Value.Count &gt; 0)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 string&#x5B;] propValues = siteTag.Value.First().Split(';');\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 List&lt;string&gt; listpropValues = propValues.ToList();\r\n                    Property&lt;List&lt;string&gt;&gt; newSiteTagProp = new Property&lt;List&lt;string&gt;&gt;();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 newSiteTagProp.Name = SiteTagProperty;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 newSiteTagProp.Value = listpropValues;\r\n                    processedItemHolder.ItemProperties.Add(newSiteTagProp);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 catch (Exception)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 processedItemHolder.ErrorCode = UnexpectedError;\r\n\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 return processedItemHolder;\r\n}\r\n<\/pre>\n<p>The item.ItemProperties contain all the input properties received by the service. These input properties will be configured by PowerShell.<br \/>\nThe 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.<\/p>\n<p>Configure the Search Service Application to use the Content Enrichment service by using PowerShell, for an example see <a href=\"https:\/\/www.itidea.nl\/index.php\/issue-sorting-links-and-documents-based-on-title\/\">this post<\/a>. Don&#8217;t forget to set a meaningful trigger otherwise every item will be passed this service.<\/p>\n<p>Run a full crawl.<\/p>\n<p>The refinement panel now shows a nice set of single values, notice the presence of &#8216;site04|..&#8217; here:<\/p>\n<p><a href=\"https:\/\/www.itidea.nl\/wp-content\/uploads\/2015\/03\/CE2_Enriched_ManagedProperty_In_RefinementPanel.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1982\" src=\"https:\/\/www.itidea.nl\/wp-content\/uploads\/2015\/03\/CE2_Enriched_ManagedProperty_In_RefinementPanel.png\" alt=\"CE2_Enriched_ManagedProperty_In_RefinementPanel\" width=\"186\" height=\"270\" \/><\/a><\/p>\n<p>When using the refinement panel in conjunction with a content search webpart, two sites will be displayed when selecting e.g. &#8216;site02|..&#8217; as expected:<\/p>\n<p><a href=\"https:\/\/www.itidea.nl\/wp-content\/uploads\/2015\/03\/CE2_Enriched_ContentSearch.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1981 size-full\" src=\"https:\/\/www.itidea.nl\/wp-content\/uploads\/2015\/03\/CE2_Enriched_ContentSearch.png\" alt=\"CE2_Enriched_ContentSearch\" width=\"192\" height=\"410\" srcset=\"https:\/\/www.itidea.nl\/wp-content\/uploads\/2015\/03\/CE2_Enriched_ContentSearch.png 192w, https:\/\/www.itidea.nl\/wp-content\/uploads\/2015\/03\/CE2_Enriched_ContentSearch-140x300.png 140w\" sizes=\"auto, (max-width: 192px) 100vw, 192px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<h3>Summary<\/h3>\n<p>To make a multivalued propertybag a real multivalued managed property a custom content enrichment service can de developed to accomplish this.<br \/>\nAfter creating a multivalued managed property it can be used in e.g. a refinement panel.<\/p>\n<p>The intention of this post was purely to demonstrate the technique, no changes has been made to make things look pretty \ud83d\ude42<\/p>\n<h4>Note<\/h4>\n<p>Only one custom content enrichment service can be bound to a Search Service Application.<br \/>\nIf you want more properties to be processed by the service you have to configure the InputProperties, OutputProperties and don&#8217;t forget the Trigger of the EnterpriseSearchContentEnrichmentConfiguration object to handle them all.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 &#8230; <a class=\"more-link\" href=\"https:\/\/www.itidea.nl\/index.php\/creating-a-custom-multi-valued-refiner\/\">Read More &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[35],"tags":[20,44],"class_list":["post-1978","post","type-post","status-publish","format-standard","hentry","category-sharepoint-2013","tag-c","tag-sharepoint-2013"],"_links":{"self":[{"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/posts\/1978","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/comments?post=1978"}],"version-history":[{"count":6,"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/posts\/1978\/revisions"}],"predecessor-version":[{"id":1989,"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/posts\/1978\/revisions\/1989"}],"wp:attachment":[{"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/media?parent=1978"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/categories?post=1978"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/tags?post=1978"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}