Update Search Result Web Part: Query Text and Result Source

I had to automate update of result source and query of a search result web part in a search page as part of deployment script to move changes from DEV to TEST, UAT and PROD.

The XML definition of a search result web part is

<webParts>
<webPart xmlns=”http://schemas.microsoft.com/WebPart/v3″&gt;
<metaData>
<type name=”Microsoft.Office.Server.Search.WebControls.ResultScriptWebPart, Microsoft.Office.Server.Search, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” />
<importErrorMessage>Cannot import this Web Part.</importErrorMessage>
</metaData>
<data>
<properties>
<property name=”MaxPagesBeforeCurrent” type=”int”>4</property>
<property name=”ShowBestBets” type=”bool”>True</property>
<property name=”Height” type=”string” />
<property name=”AdvancedSearchPageAddress” type=”string”>advanced.aspx</property>
<property name=”AllowZoneChange” type=”bool”>True</property>
<property name=”UseSharedDataProvider” type=”bool”>False</property>
<property name=”ShowPreferencesLink” type=”bool”>True</property>
<property name=”EmptyMessage” type=”string” />
<property name=”ScrollToTopOnRedraw” type=”bool”>True</property>
<property name=”ShowDefinitions” type=”bool”>True</property>
<property name=”SelectedPropertiesJson” type=”string”>null</property>
<property name=”ShowViewDuplicates” type=”bool”>False</property>
<property name=”CatalogIconImageUrl” type=”string” />
<property name=”RepositionLanguageDropDown” type=”bool”>True</property>
<property name=”PreloadedItemTemplateIdsJson” type=”string”>[“~sitecollection/_catalogs/masterpage/Display Templates/Search/Group_Default.js”,”~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_Default.js”,”~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_Site.js”,”~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_Word.js”,”~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_PowerPoint.js”,”~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_Person_CompactHorizontal.js”,”~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_BestBet.js”,”~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_WebPage.js”]</property>
<property name=”ResultsPerPage” type=”int”>10</property>
<property name=”EmitStyleReference” type=”bool”>True</property>
<property name=”ShowPaging” type=”bool”>True</property>
<property name=”ResultTypeId” type=”string” />
<property name=”ShowUpScopeMessage” type=”bool”>False</property>
<property name=”AllowMinimize” type=”bool”>True</property>
<property name=”AllowClose” type=”bool”>True</property>
<property name=”HelpMode” type=”helpmode”>Modeless</property>
<property name=”Title” type=”string”>Search Results</property>
<property name=”ShowResults” type=”bool”>True</property>
<property name=”MaxPagesAfterCurrent” type=”int”>1</property>
<property name=”ShowResultCount” type=”bool”>True</property>
<property name=”Hidden” type=”bool”>False</property>
<property name=”ItemTemplateId” type=”string” />
<property name=”ItemBodyTemplateId” type=”string”>~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_CommonItem_Body.js</property>
<property name=”UseSimplifiedQueryBuilder” type=”bool”>False</property>
<property name=”HitHighlightedPropertiesJson” type=”string”>[“Title”,”Path”,”Author”,”SectionNames”,”SiteDescription”]</property>
<property name=”AvailableSortsJson” type=”string”>[{“name”:”Relevance”,”sorts”:[]},{“name”:”Date(Newest)”,”sorts”:[{“p”:”Write”,”d”:1}]},{“name”:”Date(Oldest)”,”sorts”:[{“p”:”Write”,”d”:0}]},{“name”:”Lifetime Views”,”sorts”:[{“p”:”ViewsLifeTime”,”d”:1}]},{“name”:”Recent Views”,”sorts”:[{“p”:”ViewsRecent”,”d”:1}]}]</property>
<property name=”DataProviderJSON” type=”string”>{“QueryGroupName”:”Default”,”QueryPropertiesTemplateUrl”:”sitesearch://webroot”,”IgnoreQueryPropertiesTemplateUrl”:false,”SourceID”:null,”SourceName”:null,”SourceLevel”:null,”CollapseSpecification”:””,”QueryTemplate”:”{searchboxquery}”,”FallbackSort”:null,”FallbackSortJson”:”null”,”RankRules”:null,”RankRulesJson”:”null”,”AsynchronousResultRetrieval”:false,”SendContentBeforeQuery”:true,”BatchClientQuery”:true,”FallbackLanguage”:-1,”FallbackRankingModelID”:””,”EnableStemming”:true,”EnablePhonetic”:false,”EnableNicknames”:false,”EnableInterleaving”:true,”EnableQueryRules”:true,”EnableOrderingHitHighlightedProperty”:false,”HitHighlightedMultivaluePropertyLimit”:-1,”IgnoreContextualScope”:false,”ScopeResultsToCurrentSite”:false,”TrimDuplicates”:true,”Properties”:{},”PropertiesJson”:”{}”,”ClientType”:”AllResultsQuery”,”UpdateAjaxNavigate”:true,”SummaryLength”:180,”DesiredSnippetLength”:90,”PersonalizedQuery”:false,”FallbackRefinementFilters”:null,”IgnoreStaleServerQuery”:true,”RenderTemplateId”:””,”AlternateErrorMessage”:null,”Title”:””}</property>
<property name=”ChromeState” type=”chromestate”>Normal</property>
<property name=”AllowHide” type=”bool”>True</property>
<property name=”AllowEdit” type=”bool”>True</property>
<property name=”StatesJson” type=”string”>{}</property>
<property name=”RenderTemplateId” type=”string” />
<property name=”ShowPersonalFavorites” type=”bool”>True</property>
<property name=”ShowSortOptions” type=”bool”>False</property>
<property name=”ChromeType” type=”chrometype”>None</property>
<property name=”AllowConnect” type=”bool”>True</property>
<property name=”HelpUrl” type=”string” />
<property name=”ShowLanguageOptions” type=”bool”>True</property>
<property name=”Description” type=”string”>Displays the search results and the properties associated with them.</property>
<property name=”ServerIncludeScriptsJson” type=”string”>null</property>
<property name=”TitleUrl” type=”string” />
<property name=”AlternateErrorMessage” type=”string” null=”true” />
<property name=”ShowAlertMe” type=”bool”>True</property>
<property name=”ShowDidYouMean” type=”bool”>True</property>
<property name=”QueryGroupName” type=”string”>Default</property>
<property name=”Width” type=”string” />
<property name=”ShowAdvancedLink” type=”bool”>True</property>
<property name=”ExportMode” type=”exportmode”>All</property>
<property name=”Direction” type=”direction”>NotSet</property>
<property name=”BypassResultTypes” type=”bool”>False</property>
<property name=”GroupTemplateId” type=”string” />
<property name=”TitleIconImageUrl” type=”string” />
<property name=”MissingAssembly” type=”string”>Cannot import this Web Part.</property>
</properties>
</data>
</webPart>
</webParts>

 

The webpart property DataProviderJSON needs to be updated. The property is  in Json format which is converted to JSON using PowerShell ConvertFrom-Json method. The PowerShell ConvertTo-Json method is used to convert back to JSON before updating the “DataProviderJSON ” property.

The properties SourceId and SourceName refer to the result source.

On SharePoint On Premises environment , the SourceId can be found from navigating to central administration>Manage Service Applications>Search Service application>Result Sources.editresultsource

The format of the URL is http:///_admin/search/EditResultSourceSSA.aspx?level=service&appid={c21b4115-4e78-4d93-a4e7-24a9472c9b19}&sourceid=886883b4%2Db44c%2D4870%2Da0ff%2D1c0f81b2d9c8

In SharePoint Online, navigate to SharePoint Admin>Search>Manage Result sources and click on the result source you wish to find Id. The URL format is

https://-admin.sharepoint.com/_layouts/15/searchadmin/EditResultSource.aspx?level=tenant&sourceid=203fba36-2763-4060-9931-911ac8c0583b&view=1

Extract and decode the sourceid parameter from the url.

To update the query text, the QueryTemplate  needs to be changed. In the example below it is set to value “contentclass:STS_Web contentclass:STS_Site -SPSiteURL:personal {searchboxquery}” which means returns all sites or web based on the search criteria.

Referring to my post “Add Refiners to Refinement web part“, I had to write a script in PowerShell using CSOM SharePoint assemblies to update the result web part property DataProviderJSON.

searchresultsquerytextselectaquery

Use the following script to call function UpdateSearchResultsDataProviderWebPart .

$ctx=New-Object Microsoft.SharePoint.Client.ClientContext($SiteCollectionUrl);
$ctx.Credentials = New-Object System.Net.NetworkCredential($Username, $password);
$rootWeb = $ctx.Web
$ctx.Load($rootWeb)
$ctx.ExecuteQuery();
UpdateSearchResultsDataProviderWebPart -ctx $ctx -pageUrl "/Search/Pages/SiteDirectory.aspx"

Advertisements

Add Refiner to Refinement Web Part using CSOM and PowerShell

The refinement web part present by default on a search results page help to narrow down search results. The inter connected web parts present in a search result page are

  1. Search Box Web Part
  2. Search Navigation
  3. Search Results
  4. Refinement Web Part

The refinement web part used refiners which are managed properties bound to crawled properties created by search crawl. The managed properties must be enabled as refiners to be able to use on the web part.

newrefineraddedtowebpart

By default, the refiners FileType, contentclass, contentTypeId, WebTemplate, DisplayAuthor and LastModifiedTime are available to select.

The XML definition of the webpart is

<webParts>
<webPart xmlns=”http://schemas.microsoft.com/WebPart/v3″&gt;
<metaData>
<type name=”Microsoft.Office.Server.Search.WebControls.RefinementScriptWebPart, Microsoft.Office.Server.Search, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” />
<importErrorMessage>Cannot import this Web Part.</importErrorMessage>
</metaData>
<data>
<properties>
<property name=”StatesJson” type=”string”>{}</property>
<property name=”HelpUrl” type=”string” />
<property name=”ServerIncludeScriptsJson” type=”string”>null</property>
<property name=”Height” type=”string” />
<property name=”TitleUrl” type=”string” />
<property name=”SelectedRefinementControlsJson” type=”string”>{“refinerConfigurations”:[{“sortBy”:0,”sortOrder”:0,”maxNumberRefinementOptions”:21,”propertyName”:”FileType”,”type”:”Text”
,”displayTemplate”:”~sitecollection/_catalogs/masterpage/Display Templates/Filters/Filter_Default.js”,”displayName”:””,”useDefaultDateIntervals”:false,”aliases”:[“format”],”refinerSpecStringOverride”:””
,”intervals”:null},{“propertyName”:”contentclass”,”displayName”:null,”displayTemplate”:”~sitecollection/_catalogs/masterpage/Display Templates/Filters/Filter_Default.js”,”maxNumberRefinementOptions”:10
,”type”:”Text”,”refinerSpecStringOverride”:null,”useDefaultDateIntervals”:false,”isInherited”:false,”sortBy”:0,”sortOrder”:0,”intervals”:null,”aliases”:[“DAV:contentclass”]},{“propertyName”:”ContentTypeId”
,”displayName”:null,”displayTemplate”:”~sitecollection/_catalogs/masterpage/Display Templates/Filters/Filter_Default.js”,”maxNumberRefinementOptions”:15,”type”:”Text”,”refinerSpecStringOverride”:null
,”useDefaultDateIntervals”:false,”isInherited”:false,”sortBy”:0,”sortOrder”:0,”intervals”:null,”aliases”:null},{“propertyName”:”WebTemplate”,”displayName”:null
,”displayTemplate”:”~sitecollection/_catalogs/masterpage/Display Templates/Filters/Filter_Default.js”,”maxNumberRefinementOptions”:10,”type”:”Text”,”refinerSpecStringOverride”:null
,”useDefaultDateIntervals”:false,”isInherited”:false,”sortBy”:0,”sortOrder”:0,”intervals”:null,”aliases”:null},{“propertyName”:”DisplayAuthor”,”displayName”:null
,”displayTemplate”:”~sitecollection/_catalogs/masterpage/Display Templates/Filters/Filter_Default.js”,”maxNumberRefinementOptions”:9,”type”:”Text”,”refinerSpecStringOverride”:null
,”useDefaultDateIntervals”:false,”isInherited”:false,”sortBy”:0,”sortOrder”:0,”intervals”:null,”aliases”:null},{“propertyName”:”LastModifiedTime”,”displayName”:null
,”displayTemplate”:”~sitecollection/_catalogs/masterpage/Display Templates/Filters/Filter_SliderBarGraph.js”,”maxNumberRefinementOptions”:0,”type”:”DateTime”
,”refinerSpecStringOverride”:null,”useDefaultDateIntervals”:true,”isInherited”:false,”sortBy”:0,”sortOrder”:0,”intervals”:null,”aliases”:[“Write”,”FileWrite”,”DAV:getlastmodified”]},{“sortBy”:0
,”sortOrder”:0,”maxNumberRefinementOptions”:15,”propertyName”:”RefinableString00″,”type”:”Text”,”displayTemplate”:”~sitecollection/_catalogs/masterpage/Display Templates/Filters/Filter_Default.js”
,”displayName”:”Directorate”,”useDefaultDateIntervals”:false,”aliases”:null,”refinerSpecStringOverride”:””,”intervals”:null},{“sortBy”:0
,”sortOrder”:0,”maxNumberRefinementOptions”:15,”propertyName”:”RefinableString01″,”type”:”Text”,”displayTemplate”:”~sitecollection/_catalogs/masterpage/Display Templates/Filters/Filter_Default.js”
,”displayName”:”Status”,”useDefaultDateIntervals”:false,”aliases”:null,”refinerSpecStringOverride”:””,”intervals”:null}]}</property>
<property name=”AllowConnect” type=”bool”>True</property>
<property name=”RenderTemplateId” type=”string”>~sitecollection/_catalogs/masterpage/Display Templates/Filters/Control_Refinement.js</property>
<property name=”AllowZoneChange” type=”bool”>True</property>
<property name=”EmptyMessage” type=”string” />
<property name=”ExportMode” type=”exportmode”>All</property>
<property name=”AllowHide” type=”bool”>True</property>
<property name=”AllowEdit” type=”bool”>True</property>
<property name=”Description” type=”string”>This webpart helps the users to refine search results</property>
<property name=”AllowMinimize” type=”bool”>True</property>
<property name=”ChromeType” type=”chrometype”>None</property>
<property name=”ChromeState” type=”chromestate”>Normal</property>
<property name=”CatalogIconImageUrl” type=”string” />
<property name=”HelpMode” type=”helpmode”>Modeless</property>
<property name=”TitleIconImageUrl” type=”string” />
<property name=”Width” type=”string” />
<property name=”AlternateErrorMessage” type=”string” null=”true” />
<property name=”Hidden” type=”bool”>False</property>
<property name=”Title” type=”string”>Refinement</property>
<property name=”AllowClose” type=”bool”>True</property>
<property name=”MissingAssembly” type=”string”>Cannot import this Web Part.</property>
<property name=”UseManagedNavigationRefiners” type=”bool”>False</property>
<property name=”QueryGroupName” type=”string”>Default</property>
<property name=”EmitStyleReference” type=”bool”>True</property>
<property name=”Direction” type=”direction”>NotSet</property>
</properties>
</data>
</webPart>
</webParts>

To modify the collection of refiners the property “SelectedRefinementControlsJson” which is in Json format needs to be updated.

The property “SelectedRefinementControlsJson” is converted to JSON using PowerShell ConvertFrom-Json method before additional refiners are added. The PowerShell ConvertTo-Json method is used to convert back to JSON before updating the “SelectedRefinementControlsJson” property.

Search Display Template js file not created when HTML file for Item_ThreeLines is created

On a SharePoint Online site collection where Publishing feature was initially turned on and subsequently turned off, js file was not automatically created/updated whenever a display template was created/edited.

We wanted to have a search content web part with three lines instead of two lines. We created a new display template by following the steps below.

  • Navigate to Site Settings>Master Pages>Display Templates>Content Web Parts.
  • Download the file Item_TwoLines.html
  • Rename it to Item_ThreeLines.html
  • Edit title to Three Lines and wherever reference to Line 2 is made add corresponding reference to Line 3

  • Import the file into the  Site Settings>Master Pages>Display Templates>Content Web Parts library

However the js file was not created automatically since publishing feature was turned off.

The only option was to create the html display template in a site collection with publishing feature turned on, wait until the js is created automatically and migrate the js file and HTML file into the site collection where publishing feature is turned off. If the properties below are not set automatically, manually set the highlighted properties while uploading.

Item_ThreeLinesjs

The Item Template is accessible from any search web part added to the non publishing site collection

3_lines_Content_By_Search_WP.png

ustom Layout Results Page to allow sorting and filtering by property

Content query webpart does not give the same flexibility as search results page to allow user to filter and sort by property.

SharePoint Online provides out of the box display template which can be used in results page. However if custom property needs to be displayed or a custom display format is needed , then a new search result page can be created.

Assuming news items need to be displayed in the following format with filters Country and Subject.

SearchResultPage

  1. Map Managed Metadata fields to managed properties                  Country and Subject are managed metadata fields. Two crawled properties are created per managed metadata fields. For example field country has two crawled properties ows_taxId_Country and ows_Country. The ows_FieldName format stores the friendly label and is not mapped by default. The latter can be mapped to the out of the box refinable string mapped properties.

RefinableStrings

2.  Create  Result Source for the news

NewsResultSource.png

3.Create a new result display template “Item_NewsArticle.html” by following the guide

http://www.ableblue.com/blog/archive/2013/06/05/introduction-to-sharepoint-2013-display-templates/

The Item_NewsArticle.js gets generated automatically.

Download Item_NewsArticle.html

  1. On the news article results page, ensure the search results web part uses the template “New Article Item” and the query use the ” All News Article” result source created in previous steps.

 

 

Date Crawled properties Search SharePoint Online KQL Optional Date Filter if Date is null

CrawledDateMappedDateTime.JPGCrawled date fields from SharePoint Online are mapped to string properties which make it hard to apply a date filter on search results.

CrawledDate

If the filter EndDateOWSDATE is used in a Content Search Web Part, it won’t work as the mapped property EndDateOWSDATE  is of type text

-EndDateOWSDATE :1900-01-01..{Today}

Instead the crawled property ows_EndDate can be mapped to any out of box refinable date properties, i.e. RefinableDate00 and the filter will work.

-RefinableDate00:1900-01-01..{Today}

The filter above means returns all items with end date not within the past(i.e. not ended) . The negative (-) sign means exclude while the 1900-01-01..{Today} means between 1900-01-01 and Today’s  date.

You might be thinking just using

RefinableDate00>{Today}

will work.

The range option(..) together with the negative sign(-) is used to cater for the fact that end date can be null in which case ignore the filter. It means exclude all ended items without excluding items with no end date.

If today’s date need to fall between  start date and end date of items assuming start date field has been mapped to RefinableDate02 the following filter can be used

-RefinableDate01:1900-01-01..{Today-1} -RefinableDate02:{Today+1}..3000-12-31

Range .. Is used in the filter to ignore the condition is the date value is empty. The above filter will ignore all end dates ranging from 1900-01-01 to {today-1} and start dates ranging from {today+1} to 3000-12-3 but criteria will be ignored if date is empty or null.

 

 

 

 

KQL SharePoint Online filtering on user profile multi values managed metadata properties

Keyword Query Language (KQL) is a powerful way to query search results in SharePoint Online.

It is possible to filter data based on the user profile property ,e.g. owstaxidJobTitle:{User.SPS-JobTitle}

The above is a valid property restriction which will return all items having the managed metadata field JobTitle equal to the user profile property JobTitle of the logged in user.

When managed metadata field is crawled, two crawled properties are created in the format of ows_taxid_ and ows_. The ows_taxid_ is mapped to managed property owstaxid. The managed property owstaxidJobTitle stores the crawled property of the managed metadata field JobTitle.

Let’s say if user profile managed metadata property is multi valued. All items matching all the values in the user profile managed metadata property need to be returned.

The KQL achieves the goal of returning all items with managed metadata field ItemTopic contain any terms tagged against the “Ask Me About” field of the logged in user assuming the “Ask Me About” has been mapped to a term set.

{?{|owstaxIdItemTopic:{User.SPS-Responsibility}}}

SPS-Responsibility is the internal name of “Ask Me About” field from user profile.

The above snippets can be tested using the Content Search Web Part.