Saturday, November 8, 2014

One problem with “Value of a parameter from URL” query variable in Sharepoint 2013 search queries

There are several ways to customize search queries in Sharepoint. One of them is to edit query in appropriate search result source used in the site collection (Site settings > Search result source). When you will click Launch query builder button popup window will be opened which will allow to modify search query by applying additional filters. You may add keywords filters and property filters there. Property filter means that you will add condition for managed property used in the crawled content. You may use hardcoded value in rvalue for the condition or one of the available query variables which will be replaced with the real value in runtime:

image

One of the interesting values is “Value of a parameter from URL” as it allows to modify search queries in runtime. Another value which looks applicable for this is “Value of a field on the page”. Based on it’s name you may think that it allows to use html field (e.g. hidden field) on the page, but unfortunately it means metadata field from the current search results page, like specified in Query variables in SharePoint Server 2013:

The value of a field on the page from where the query was issued. For example, if the page from where the query was issued contained a site column named "ContentOwner," specifying {Page.ContentOwner} would allow you to query for the value of "ContentOwner."

So if we need to modify search query in runtime there are not so many options. We may use mentioned “Value of a parameter from URL” or “Value of a token from URL”. But since programmatically it is easier to add query string parameter comparing with constructing URL routes for using tokens, first option is used more frequently.

Condition which uses “Value of a parameter from URL” variable looks like this:

ManagedProperty={QueryString.ParamName}

where ManagedProperty should be the name of managed property for which you add the condition and ParamName – name of the query string parameter. Also in this example we used equals (=) operator, while you may also use other available operators (see Keyword Query Language (KQL) syntax reference for examples) e.g.

Title={QueryString.Title}

If in this case we will pass ?title=foo in query string, search condition will be evaluated to Title=foo. This technique looks good, but there are several problems which you need to aware when will use it. First of all query string parameter should be defined before search query parameter (k=…). I.e. if you have search results page http://example.com/search.aspx and by default search queries looks like this: http://example.com/search.aspx?k=bar, then you need to add additional query string parameter before “k” parameter:

http://example.com/search.aspx?title=foo&k=bar

Otherwise search will look for the content which contains “bar&title=foo” phrase which is incorrect of course. Note also that when user changes search query on search results page and clicks search, it happens without postback by ajax call which adds new “k” parameter after “#” sign to existing  query string. In our example it will look like this:

http://example.com/search.aspx?title=foo&k=bar#k=foobar

In this case {QueryString.Title} will be treat as empty and search won’t result any results. In order to avoid this problem we will need to add our query string parameter after “#” sign as well (also before “k”):

http://example.com/search.aspx?title=foo&k=bar#title=foo&k=foobar

You may do it by overriding javascript function which is called when user clicks search button on the search results page. However this is not the only problem with “Value of a parameter from URL” variable. Another problem is that when you use it in the queries, it is mandatory that it will have at least some value. I.e. simple search query with only “k” parameter http://example.com/search.aspx?k=bar won’t return any results. If you will check logs you will find that query parser fails in this case:

Operator Name=ParserExecutor, Message=The processing of item fails with error Exception occurred due to some other exception

and after that:

ExecuteFlowInternal Flow:Microsoft.SharePointSearchProviderFlow Exception: Microsoft.Office.Server.Search.Query.QueryEmptyException: No results are available. Either no query is specified, or the query came from advanced search (Federated Webparts do not support Advanced Search queries).

As it was mentioned workaround for this problem is to add title with at least some value to the query string:

http://example.com/search.aspx?title=any&k=bar

and then in query builder add condition which won’t filter content by value specified in query string in this case, e.g. like this:

{QueryString.Title}=any OR Title={QueryString.Title}

That’s why also it is important to add query string parameter after “#” sign when user clicks search button on search results page. Hope that this information will help someone.

Update 2014-11-19. Further investigation showed that this problem only appears when you use top-level curly braces in your search result source’s query, e.g.:

{?{searchTerms} -ContentClass=urn:content-class:SPSPeople}

But if you remove them

?{searchTerms} -ContentClass=urn:content-class:SPSPeople

then search become working even when query string variable is not specified, while other conditions still work as expected. This still may be a problem because OTB “Local SharePoint Results” result source uses query with top-level braces.

No comments:

Post a Comment