Thursday, December 12, 2013

Auto Suggest Using Solr - Configuring with SolrJ for Java Web Applications

I was tasked with setting up an auto suggest feature for the e-commerce site that we were working on and I had chosen Solr's auto suggest feature as

1. The ecommerce site was already running on Solr for its search
2. Required minimal config changes.

The challenge though, was that the Solr service was being run as an embedded server and hence I had to contact the server only through the SolrJ library.

Firstly , we have to make a few changes to the schema.xml and solrconfig.xml files to get this working

schema.xml

1. Define a new field type "auto_suggest" in your schema.xml

<fieldType name="auto_suggest" class="solr.TextField" > 
 <analyzer> 
  <tokenizer class="solr.KeywordTokenizerFactory"/> 
  <filter class="solr.LowerCaseFilterFactory"/> 
  </analyzer> 
</fieldType>

2. Define a new field "autocomplete_text" of type "auto_suggest" in your schema.xml

<field name="autocomplete_text" type="auto_suggest" indexed="true" stored="false"  multiValued="true" />

3. Define a copyField to copy all the fields (on which you want the auto suggest to work ) to the newly created field

<copyField source="*" dest="autocomplete_text"/> 

solrconfig.xml

1. Put in the following search component and request handler to handle the auto suggest terms

<searchComponent name="terms" class="solr.TermsComponent"/>
 
 <requestHandler name="/terms" class="solr.SearchHandler" startup="lazy">
 <lst name="defaults">
      <bool name="terms">true</bool>
      <bool name="distrib">false</bool>
  </lst>
  <arr name="components">
       <str>terms</str>
  </arr>
</requestHandler>

Secondly , we would need to write some java code to get the results from the embedded solr server

Java Code

public List<String> typeAhead(String q) throws SolrServerException{
SolrQuery query = new SolrQuery();
query.setParam(CommonParams.QT, "/terms"); //specify the request handler mapping as mentioned in solrconfig.xml 
query.setParam(TermsParams.TERMS, true); 
query.setParam(TermsParams.TERMS_LIMIT, "10"); // specifies the number of results
query.setParam(TermsParams.TERMS_FIELD, "autocomplete_text");  // or whatever fields you want
query.setParam(TermsParams.TERMS_PREFIX_STR, q); // pass the query prefix string
List<String> typeAheadList = new ArrayList<String>();
QueryResponse response = solrServer.query(query);  // SolrServer has to be replaced with your solr server instance
TermsResponse tr = response.getTermsResponse();
List<Term> termList = tr.getTerms("autocomplete_text");
for(Term t : termList){
typeAheadList.add(t.getTerm());
}
return typeAheadList ;
}

Sample

Input  -  a
Output  - absolute ,actor ,actress, address ,

Input  - ac
Output  - actor,actress

Input  - heater co
Output - heater coil , heater core

I have not tested this out on a stand alone solr server, but I don't see a reason as to why it should not work on one.


No comments:

Post a Comment