sort by "termfreq" Solr function doesn't work

Hi,

in our case we have to show first the items, where the field "memberlist" contains the current user id. In Solr it is possible to sort by the function "numFound(fieldName, fieldValue)":

 

the function returns the number of matches in a single field.

Unfortunatelly, this query in solr and it doesn't work in Telligent. The exception is: "We apologize, but an unknown error has occurred during search. Please try your search again."

Do you know how to fix it or do you have some workaround for such case?

Parents
  • The properties for filters and sorting are indended for simple "fieldname:value(s) (filters) and "fieldname asc/desc, [optional] another field asc/desc" usage from the API. This is intentional to ensure a supportable API and security. When it comes to more advanced, Solr specific functions the current recommendation is to 1) use a unique place holder in the field that matches the expected format (ex. termfreqUser:someValue) and 2) pickup/intercept this format using the Solr specific search events to manipulate the query before being sent. This can be done using an automation - see this event and reference the SolrOptions.Url.

  • Could you provide me with an example how to assign a custom event handler to the BeforeSearch event?

  • Here is an quick example automation that would do something similar. I am not sure what 'memberlist' is in your example but it doesnt matter since of course you can this to do whatever you need.

    This automation:

    • Attaches to the SolrEvents.BeforeSearch
    • Expects a format for this custom sort to be 'customTermSort desc' and replaces it with "termFreq(user,[currentUserid]) desc". Note: I used 'user' here since I dont have 'memberlist'.

    To use this:

    1. Import the automation by going to Automation Studio and clicking the + icon. Take a peek at the code Slight smile
    2. Goto Administration -> Automations -> Add -> Select 'Search Query Adjustments' to create an instance of this automation.
    3. Test using the Script Sandbox which is in any of the Studios. You can use the following to issue a search.
      #set($searchResultsResponse = $core_v2_searchResult.List("%{ Query= 'test', Sort='customTermSort desc'}")) 
      
        

    <automation name="Search Query Adjustments" version="11.0.0.0" description="" id="f56d93a981f845678bbd8b93fe18d2d2" executeAsServiceUser="false" isSingleton="false" trigger="Event" lastModified="2020-06-25 16:50:15Z">
    	<events>
    		<event key="solr.beforesearch" />
    	</events>
    	<executionScript language="JavaScript"><![CDATA[var solrOptions = context_v2_automationTrigger.Arguments.SolrOptions;
    if (!solrOptions || !solrOptions.Url) {
        return;
    } 
    
    var customSortLookingFor ="customTermSort desc";
    
    //NOTE: Do not leave event logs in!!!! 
    //core_v2_eventLog.Write("Before: " + solrOptions.Url); 
    
    var qs = parseQuery(solrOptions.Url);
    
    if (!qs || !qs["sort"] || qs["sort"] != customSortLookingFor) {
        return;
    }
    
    qs["sort"] = "termfreq(user," + context_v2_automationTrigger.TriggeredBy.Id + ") desc";
    var adjustedUrl = getHost(solrOptions.Url) + "?" + serializeQuery(qs);
    
    //core_v2_eventLog.Write("After/Final: " + adjustedUrl);
    
    return adjustedUrl;
    
    function parseQuery (queryString) {
    	var parts = queryString.split('?'),
    		raw = (parts.length > 1 ? parts[1] : queryString).split('#')[0],
    		data = {},
    		pairs = raw.split('&');
    
    	pairs.forEach(function(pair, i) {
    		pair = pair.split('=');
    		if (pair.length === 2) {
    			data[decodeURIComponent(pair[0].replace(/\+/gi, ' '))] = decodeURIComponent(pair[1].replace(/\+/gi, ' '));
    		}
    	});
    
    	return data;
    }
    
    function serializeQuery (data) {
    	data = data || {};
    	var pairs = [];
    
    	for (var key in data) {
    		pairs[pairs.length] = encodeURIComponent(key) + "=" + encodeURIComponent(data[key]);
    	}
    
    	return pairs.join('&');
    }
    
    function getHost(href) {
        return href.split('?')[0];
    }]]></executionScript>
    </automation>

  • Thank you for your reply. In our project we create .net plugins to extend the Telligent logic. So I've create a class InProcessApi that implements the IApiDefinition and assigned a custom event handler for the BeforeSearch event in the Initialize method

    public void Initialize()
    {
    Apis.Get<ISolr>().Events.BeforeSearch += AokDocumentDataService.UpdateSolrSortQuery;
    }

    the event args contain two props: Options and SolrOptions, so I've tried to overwrite their values, but unfortunatelly it doesn't have any effect.

    /// <summary>
    /// Deletes individual document permissions for a user who is removed from group permissions.
    /// </summary>
    /// <param name="e">The details about the user who was deleted from a group.</param>
    internal static void UpdateSolrSortQuery(BeforeSolrSearchEventArgs e)
    {
    string sort = e.Options.Sort;

    //overwrite the sort  variable

    e.Options.Sort = sort;

    // overwrite the url with new sort value

    Uri uri = new Uri(e.SolrOptions.Url);
    var qs = HttpUtility.ParseQueryString(uri.Query);
    qs.Set("sort", e.Options.Sort);
    string newUrl = $"{uri.Scheme}://{uri.Host}{uri.AbsolutePath}?{qs}";
    e.SolrOptions.Url = newUrl;
    }


    do you know how to solve it from the .net Plugin?

Reply
  • Thank you for your reply. In our project we create .net plugins to extend the Telligent logic. So I've create a class InProcessApi that implements the IApiDefinition and assigned a custom event handler for the BeforeSearch event in the Initialize method

    public void Initialize()
    {
    Apis.Get<ISolr>().Events.BeforeSearch += AokDocumentDataService.UpdateSolrSortQuery;
    }

    the event args contain two props: Options and SolrOptions, so I've tried to overwrite their values, but unfortunatelly it doesn't have any effect.

    /// <summary>
    /// Deletes individual document permissions for a user who is removed from group permissions.
    /// </summary>
    /// <param name="e">The details about the user who was deleted from a group.</param>
    internal static void UpdateSolrSortQuery(BeforeSolrSearchEventArgs e)
    {
    string sort = e.Options.Sort;

    //overwrite the sort  variable

    e.Options.Sort = sort;

    // overwrite the url with new sort value

    Uri uri = new Uri(e.SolrOptions.Url);
    var qs = HttpUtility.ParseQueryString(uri.Query);
    qs.Set("sort", e.Options.Sort);
    string newUrl = $"{uri.Scheme}://{uri.Host}{uri.AbsolutePath}?{qs}";
    e.SolrOptions.Url = newUrl;
    }


    do you know how to solve it from the .net Plugin?

Children