Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the suggester component working in SolrNet?

I have configured my solrconfig.xml and schema.xml to query for the suggestions.

I am able to get the suggestions from the url

http://localhost:8080/solr/collection1/suggest?q=ha&wt=xml

My SolrConfig.xml looks like

Curently, My solr query looks like

<fields>
    <!-- declare fields of entity class -->
    <!-- type will specify the table name -->
    <field name="type" type="string" indexed="true" stored="true"  />

    <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
    <field name="name" type="text_general" indexed="true" stored="true" omitNorms="true"/>

    <field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>
    <field name="_version_" type="long" indexed="true" stored="true"/>

    <!-- unique field -->
    <field name="uid" type="uuid" indexed="true" stored="true" />

  </fields>

  <uniqueKey>uid</uniqueKey>

  <copyField source="name" dest="text"/>

  <types>
    <fieldType name="uuid" class="solr.UUIDField" indexed="true" />
    <fieldType name="string" class="solr.StrField" sortMissingLast="true" />
    <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>

    <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
    .....
    </types>

And my schema.xml looks like this

<searchComponent name="suggest" class="solr.SpellCheckComponent">
    <!-- a spellchecker built from a field of the main index -->
    <lst name="spellchecker">
      <str name="name">suggest</str>
      <str name="field">name</str>
      <str name="classname">org.apache.solr.spelling.suggest.Suggester</str>
      <str name="lookupImpl">org.apache.solr.spelling.suggest.tst.TSTLookup</str>
      <str name="buildOnCommit">true</str>          
      <str name="distanceMeasure">internal</str>
      <float name="accuracy">0.5</float>
      <int name="maxEdits">2</int>
      int name="minPrefix">1</int>
      <int name="maxInspections">5</int>
      <int name="minQueryLength">4</int>
      <float name="maxQueryFrequency">0.01</float>
       <float name="thresholdTokenFrequency">.01</float>      
    </lst>

    <!-- a spellchecker that can break or combine words.  See "/spell" handler below for usage -->
    <lst name="spellchecker">
      <str name="name">wordbreak</str>
      <str name="classname">solr.WordBreakSolrSpellChecker</str>
      <str name="field">name</str>
      <str name="combineWords">true</str>
      <str name="breakWords">true</str>
      <int name="maxChanges">10</int>
    </lst>
</searchComponent>

<requestHandler name="/suggest" class="solr.SearchHandler" startup="lazy">
    <lst name="defaults">
      <str name="df">text</str>
      <!-- Solr will use suggestions from both the 'default' spellchecker
           and from the 'wordbreak' spellchecker and combine them.
           collations (re-written queries) can include a combination of
           corrections from both spellcheckers -->
      <str name="spellcheck">true</str>
      <str name="spellcheck.dictionary">suggest</str>
      <!--<str name="spellcheck.dictionary">wordbreak</str>-->
      <str name="spellcheck">on</str>
      <str name="spellcheck.extendedResults">true</str>       
      <str name="spellcheck.count">10</str>
      <str name="spellcheck.alternativeTermCount">5</str>
      <str name="spellcheck.maxResultsForSuggest">5</str>       
      <str name="spellcheck.collate">true</str>
      <str name="spellcheck.collateExtendedResults">true</str>  
      <str name="spellcheck.maxCollationTries">10</str>
      <str name="spellcheck.maxCollations">5</str>         
    </lst>
    <arr name="last-components">
      <str>spellcheck</str>
    </arr>
  </requestHandler>

My code to call the SolrNet API looks as below

new SolrBaseRepository.Instance<T>().Start();
        var solr = ServiceLocator.Current.GetInstance<ISolrOperations<T>>();
        var options = new QueryOptions
        {
            FilterQueries = new ISolrQuery[] { new SolrQueryByField("type", type) }
        };
        var results = solr.Query(keyword, options);
        return results;

However, I am not getting any data. results count is zero. And also the spellcheck in the results is also zero.

I also dont see the suggestion list inside the results.

enter image description here

Please help

like image 678
Prasad Avatar asked Jan 07 '13 11:01

Prasad


2 Answers

I had the exact same requirement but could not find any way to easily handle Suggester results with SolrNet. Unfortunately, SolrNet seems to be built around the default /select request handler and does not currently support any other handler including /suggest for object type mappings (T). It expects all mappings to occur with indexed Solr document results and not suggester results.

Hence, @Paige Cook's answer did not work for me. T type with mappings is not compatible with a suggester results response. All the standard plumbing code from initializing the request (Startup.Init<T>()) to querying (ISolrQueryResults<T> results = solr.Query()) needs a mapped Solr document type and not a simple array of strings which the suggester provides.

Therefore, (similar to @dfay) I went with making a web request and parsing out the suggested results from the XML web response. The SolrConnection class was used for this:

string searchTerm = "ha";
string solrUrl = "http://localhost:8080/solr/collection1";
string relativeUrl = "/suggest";
var parameters = new Dictionary<string, string>
                {
                    {"q", searchTerm},
                    {"wt", "xml"},
                };

var solrConnection = new SolrConnection(solrUrl);
string response = solrConnection.Get(relativeUrl, parameters);
// then use your favorite XML parser to extract 
// suggestions from the reponse string

Alternatively, instead of XML, the request can return a JSON response using the wt=json parameter:

var parameters = new Dictionary<string, string>
                {
                    {"q", searchTerm},
                    {"wt", "json"}, // change this!
                };
// then use your favorite JSON parser
like image 197
Ray Avatar answered Sep 19 '22 18:09

Ray


See http://wiki.apache.org/solr/SolrRequestHandler, particularly the section on the old handleSelect=true behavior. If you are running against a newer Solr server, this is most likely your problem. (i.e. setting "qt" has no effect and either the default handler in SolrNet must be changed or the Solr config needs to set handleSelect=true.) Here's how I solved this problem in my case:

ISolrConnection connection = ServiceLocator.Current.GetInstance<ISolrConnection>();
List<KeyValuePair<string, string>> termsParams = new List<KeyValuePair<string, string>>();
termsParams.Add(new KeyValuePair<string, string>("terms.fl", "name"));
termsParams.Add(new KeyValuePair<string, string>("terms.prefix", mySearchString));
termsParams.Add(new KeyValuePair<string, string>("terms.sort", "count"));
string xml = connection.Get("/terms", termsParams);

ISolrAbstractResponseParser<Document> parser = ServiceLocator.Current.GetInstance<ISolrAbstractResponseParser<Document>>();
SolrQueryResults<Document> results = new SolrQueryResults<Document>();
parser.Parse(System.Xml.Linq.XDocument.Parse(xml), results);

TermsResults termResults = results.Terms;
foreach (TermsResult result in termResults)
{
    foreach (KeyValuePair<string, int> kvp in result.Terms)
    {
        //... do something with keys
    }
}

Basically I use the SolrNet parser and the connection code but not the query stuff. Hope this helps.

like image 33
dfay Avatar answered Sep 21 '22 18:09

dfay