Collection-based auto-completion

Managed by | Updated .

Warning

The use of collection-based auto-completion is not recommended and should be avoided unless other auto-completion options have been exhausted.   Funnelback's built-in auto-completion system is designed for speed (and minimal system overhead when the request is processed).  Using a standard query to produce query completion can result in significant load being placed on the server as a query can be fired for each user keystroke.

Occasionally Funnelback's auto-completion is too basic to service the needs of a user and it becomes necessary to use a standard Funnelback collection and padre-sw query to supply the auto-completion.

The following process can be used to deploy collection based auto-completion.

Setup process

1. Create a auto-completion profile on the collection used to deliver auto-completion suggestions

2. Add the following padre_opts.cfg.  This is to optimise the query.

padre_opts.cfg
-stem=0 -SM=off -bb=false -rmcf=[dummyvalue] -spelling=off -contextual_navigation=false -QL=0 -log=false -countgbits=63  -collapsing=false -show_qsyntax_tree=off

3. Add the following custom Freemarker template to the auto-completion profile

qc.ftl
<#ftl encoding="utf-8" />
<#import "/web/templates/modernui/funnelback_classic.ftl" as s/>
<#import "/web/templates/modernui/funnelback.ftl" as fb/>
<#escape x as x?jsonstring>
<#if question.inputParameterMap["callback"]?exists>${question.inputParameterMap["callback"]}(</#if>[
<@s.AfterSearchOnly>
<#if response.resultPacket.resultsSummary.totalMatching != 0>
<@s.Results>
<#if s.result.class.simpleName != "TierBar">
{
"key" : "<#if question.inputParameterMap["partial_query"]?exists>${question.inputParameterMap["partial_query"]?json_string}</#if>",
"disp" : "${s.result.title}",
"disp_t" : "T",
"wt" : "${s.result.score}",
"cat" : "",
"cat_t" : "1",
"action" : "${s.result.clickTrackingUrl}",
"action_t" : "U"
}<#if (s.result.rank < response.resultPacket.resultsSummary.currEnd)>,</#if>
</#if>
</@s.Results>
</#if>
</@s.AfterSearchOnly>]
<#if question.inputParameterMap["callback"]?exists>)</#if>
</#escape>

4. Add the following code to the collection's pre process hook script:

hook_pre_process.groovy
// Expand a partial query for collection_based auto-completion
// reads the partial_query CGI parameter and creates a disjunctive query based on the suggestions returned from padre-qs
// Imports required for access to the padre suggest service
import java.io.File;
import java.util.List;
import com.funnelback.dataapi.connector.padre.PadreConnector;
import com.funnelback.dataapi.connector.padre.suggest.Suggestion;
import com.funnelback.dataapi.connector.padre.suggest.Suggestion.ActionType;
import com.funnelback.dataapi.connector.padre.suggest.Suggestion.DisplayType;
 
if(transaction.question.inputParameterMap['profile'].equals("auto-completion") || transaction.question.inputParameterMap['profile'].equals("auto-completion_preview")) {
  def logger = org.apache.log4j.Logger.getLogger("partial query expander")
  def q = transaction.question
   
  // set query completion to use qc form
  q.form = "qc"
  // Convert a partial query into a set of query terms
  // Maximum number of query terms to expand partial query to - read from collection.cfg partial_query_expansion_index parameter.
  // eg. partial_query=com might expand to query=[commerce commercial common computing]
  def partial_query_expansion_index = 5
  if ((q.collection.configuration.value(["partial_query_expansion_index"]) != null) && (q.collection.configuration.value(["partial_query_expansion_index"]).isInteger())) {
    partial_query_expansion_index = q.collection.configuration.value(["partial_query_expansion_index"])
  }
   
  if (q.inputParameterMap["partial_query"] != null) {
    //File searchHome = new File("/opt/funnelback") //14.2+
    File indexStem = new File(q.collection.configuration.value(["collection_root"]) + File.separator + "live" + File.separator + "idx","index")
    // NOTE: CONSTRUCTOR HAS CHANGED post v14.2 and requires searchHome as a second param
    List<Suggestion> suggestions = new PadreConnector(searchHome, indexStem) //14.2+
    // List<Suggestion> suggestions = new PadreConnector(indexStem) //14.0 or earlier
        .suggest(q.inputParameterMap["partial_query"])
        .suggestionCount(partial_query_expansion_index)
        .fetch();
    // build the expanded query from the list of suggestions
    def expanded_query = ""
    suggestions.each {
        expanded_query += '"'+it.key+'" '
    }
    // set the number of suggestions to the value of the configured auto-completion.show
    q.additionalParameters["num_ranks"] = [q.inputParameterMap["show"]]
    // set the query to the expanded set of query terms ORed together
    if (expanded_query != "") {
        q.query = "["+expanded_query+"]"
    }
  }
}   

5. Add the following options to the collection's collection.cfg:

collection.cfg
auto-completion.program=../s/search.html
ui.modern.form.qc.content_type=application/javascript
#Optional setting to adjust number of suggestions that the partial query is expanded to
#partial_query_expansion_index=8
Was this artcle helpful?

Tags
Type: Keywords:
Features: Frontend > Auto-completion

Comments