I have set up the spellchecker for the example installation configuration that comes with Solr. I have followed their instructions for the spellchecker here: [http://wiki.apache.org/solr/SpellCheckComponent][1]
The problem I have is that after following it exactly I still cannot get it to work?
The response when I build (http://localhost:8983/solr/spell?q=:&spellcheck.build=true&spellcheck.q=delll%20ultrashar&spellcheck=true)
looks as follows:
<response>
<lst name="responseHeader">
<int name="status">0</int>
<int name="QTime">14</int>
</lst>
<str name="command">build</str>
<result name="response" numFound="17" start="0">
...
</result>
<lst name="spellcheck">
<lst name="suggestions"/>
</lst>
</response>
And when I query with http://localhost:8983/solr/spell?q=:&spellcheck.q=delll+ultrashar&spellcheck=true&spellcheck.extendedResults=true
I get the following response
<response>
<lst name="responseHeader">
<int name="status">0</int>
<int name="QTime">1</int>
</lst>
<result name="response" numFound="17" start="0">
...
</result>
<lst name="spellcheck">
<lst name="suggestions">
<bool name="correctlySpelled">false</bool>
</lst>
</lst>
</response>
What gives? Am i missing something in my schema.xml?
The schema.xml is here: http://www.developermill.com/schema.xml
The solrConfig.xml is here: http://www.developermill.com/solrconfig.xml
The only change to the example files was the addition of the following in the solrconfig.xml:
<searchComponent name="spellcheck" class="solr.SpellCheckComponent">
<lst name="spellchecker">
<!--
Optional, it is required when more than one spellchecker is configured.
Select non-default name with spellcheck.dictionary in request handler.
-->
<str name="name">default</str>
<!-- The classname is optional, defaults to IndexBasedSpellChecker -->
<str name="classname">solr.IndexBasedSpellChecker</str>
<!--
Load tokens from the following field for spell checking,
analyzer for the field's type as defined in schema.xml are used
-->
<str name="field">spell</str>
<!-- Optional, by default use in-memory index (RAMDirectory) -->
<str name="spellcheckIndexDir">./spellchecker</str>
<!-- Set the accuracy (float) to be used for the suggestions. Default is 0.5 -->
<str name="accuracy">0.7</str>
<!-- Require terms to occur in 1/100th of 1% of documents in order to be included in the dictionary -->
<float name="thresholdTokenFrequency">.0001</float>
</lst>
<!-- Example of using different distance measure -->
<lst name="spellchecker">
<str name="name">jarowinkler</str>
<str name="field">lowerfilt</str>
<!-- Use a different Distance Measure -->
<str name="distanceMeasure">org.apache.lucene.search.spell.JaroWinklerDistance</str>
<str name="spellcheckIndexDir">./spellchecker</str>
</lst>
<!-- This field type's analyzer is used by the QueryConverter to tokenize the value for "q" parameter -->
<str name="queryAnalyzerFieldType">textSpell</str>
</searchComponent>
<!--
The SpellingQueryConverter to convert raw (CommonParams.Q) queries into tokens. Uses a simple regular expression
to strip off field markup, boosts, ranges, etc. but it is not guaranteed to match an exact parse from the query parser.
Optional, defaults to solr.SpellingQueryConverter
-->
<queryConverter name="queryConverter" class="solr.SpellingQueryConverter"/>
<!-- Add to a RequestHandler
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
NOTE: YOU LIKELY DO NOT WANT A SEPARATE REQUEST HANDLER FOR THIS COMPONENT. THIS IS DONE HERE SOLELY FOR
THE SIMPLICITY OF THE EXAMPLE. YOU WILL LIKELY WANT TO BIND THE COMPONENT TO THE /select STANDARD REQUEST HANDLER.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-->
<requestHandler name="/spellCheckCompRH" class="solr.SearchHandler">
<lst name="defaults">
<!-- Optional, must match spell checker's name as defined above, defaults to "default" -->
<str name="spellcheck.dictionary">default</str>
<!-- omp = Only More Popular -->
<str name="spellcheck.onlyMorePopular">false</str>
<!-- exr = Extended Results -->
<str name="spellcheck.extendedResults">false</str>
<!-- The number of suggestions to return -->
<str name="spellcheck.count">1</str>
</lst>
<!-- Add to a RequestHandler
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
REPEAT NOTE: YOU LIKELY DO NOT WANT A SEPARATE REQUEST HANDLER FOR THIS COMPONENT. THIS IS DONE HERE SOLELY FOR
THE SIMPLICITY OF THE EXAMPLE. YOU WILL LIKELY WANT TO BIND THE COMPONENT TO THE /select STANDARD REQUEST HANDLER.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-->
<arr name="last-components">
<str>spellcheck</str>
</arr>
</requestHandler>
The textSpell field definition is in the wrong place. The following fragment should be within the types tag inside the schema.xml:
<fieldType name="textSpell" class="solr.TextField" positionIncrementGap="100" omitNorms="true">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.StandardFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.StandardFilterFactory"/>
</analyzer>
</fieldType>
After you've fixed that, everything should work I guess, but I'd suggest you to work on cleaning up a little bit your example, since it basically contains everything you can configure. You should keep just what you really need.
Related
I am trying to implement scoped autosuggestions like in ecommerce websites like amazon etc.
eg.
if i type Lego , the suggestions should come like
Legolas in Names
Lego in Toys
where Names and Toys are solr field names.
closest aid i got is from this discussion:
solr autocomplete with scope is it possible?
Which informed me that it isn't possible with the suggester which I am currently using.
Until now, using the suggester I am able to achieve autosuggestions from a single solr field. [the autosuggest field , following guidelines in the suggester documentation]
Any ideas/links to help me with ?
Update
I tried to achieve autosuggestions using facets. My query looks something like:
http://localhost:8983/solr/core1/select?q=*%3A*&rows=0&wt=json&indent=true&facet=true&facet.field=field1&facet.field=field2&facet.prefix=i
This gives me all the facet results starting with letter 'i' and term faceted to field1 and field2.
This gave me the idea.
Any comments?
I am assuming you are storing the Names or Toys data as in a field, let call it category.
You can configure the payloadField parameter in the searchComponent definition and pass the category data into it. Later in the application when you receive the suggestion results from solr, show first suggestion from each category or which ever strategy suits better for your use case.
You can find the more information in Solr Suggester.
Suggester component seems useful but in payload field, one can only return a single field which may not satisfy many of the use cases.
By Facet prefixing, you cannot get suggestions from a word in the middle. So "Lego" will give suggestion of a product whose value in name field is "Legolas Sample" but not from "Sample Legolas".
The third way is to implement autosuggest is by using a index analyzer that has a layer of EdgeNGramFilterFactory and then searching on the required prefix.
So, the solr schema will look like
<field name="names" type="string" multiValued="false" indexed="true" stored="true"/>
<field name="toys" type="string" multiValued="false" indexed="true" stored="true"/>
<field name="names_ngram" type="text_suggest_ngram" multiValued="false" indexed="true" stored="false"/>
<field name="toys_ngram" type="text_suggest_ngram" multiValued="false" indexed="true" stored="false"/>
and the field type would have a definition of
<fieldType name="text_suggest_ngram" class="solr.TextField" positionIncrementGap="100" multiValued="true">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.EdgeNGramFilterFactory" maxGramSize="10" minGramSize="2"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
and these _ngram fields would be a copyfield:
<copyField source="names" dest="names_ngram"/>
<copyField source="toys" dest="toys_ngram"/>
So , once you have reindexed your data, if you query for "Lego" it will give results from both "Sample Legolas" and "Legolas Sample". However, if you have to categorize these results according to n fields they matched, that would be n different queries which is usually not a problem.
You can add multiple suggester components.
Add one for each field.
E.g. :
<searchComponent name="suggest" class="solr.SuggestComponent">
<lst name="suggester">
<str name="name">namesSuggester</str>
<str name="lookupImpl">BlendedInfixLookupFactory</str>
<str name="dictionaryImpl">DocumentDictionaryFactory</str>
<str name="field">Names</str>
<str name="weightField">Popularity</str>
<str name="indexPath">namesSuggesterIndexDir</str>
<str name="suggestAnalyzerFieldType">suggester</str>
</lst>
<lst name="suggester">
<str name="name">toysSuggester</str>
<str name="lookupImpl">BlendedInfixLookupFactory</str>
<str name="dictionaryImpl">DocumentDictionaryFactory</str>
<str name="field">Toys</str>
<str name="weightField">Popularity</str>
<str name="indexPath">toysSuggesterIndexDir</str>
<str name="suggestAnalyzerFieldType">suggester</str>
</lst>
</searchComponent>
I'm using solr 5.2 and I want to use IndexBasedSpellChecker inside my searchHandler,and this is my searchcomponent for IndexBasedSpellChecker:
<searchComponent class="solr.SpellCheckComponent" name="spellcheck">
<str name="queryAnalyzerFieldType">text_en_general</str>
<lst name="spellchecker">
<str name="name">default</str>
<!--specify a field to use for the suggestions-->
<str name="field">body-en</str>
<str name="classname">solr.IndexBasedSpellChecker</str>
<!-- <str name="distanceMeasure">internal</str> -->
<!--The accuracy setting defines the threshold for a valid suggestion-->
<!-- <float name="accuracy">0.05</float> -->
<!-- maxEdits defines the number of changes to the term to allow-->
<int name="maxEdits">2</int>
<!--defines the minimum number of characters the terms should share-->
<int name="minPrefix">1</int>
<!--defines the maximum number of possible matches to review before returning results-->
<int name="maxInspections">5</int>
<!--defines how many characters must be in the query before suggestions are provided-->
<int name="minQueryLength">4</int>
<!-- sets the maximum threshold for the number of documents a term must appear in before being considered as a suggestion-->
<float name="maxQueryFrequency">0.01</float>
<!--sets the minimum number of documents a term must appear in-->
<float name="thresholdTokenFrequency">.01</float>
my problem here is that when I want to use accuracy it gives me this error
Caused by: org.apache.solr.common.SolrException: java.lang.Float cannot be cast to java.lang.String
and when I comment this setting, it will give me another error for using distanceMeasure :
org.apache.solr.common.SolrException:org.apache.solr.common.SolrException: Error loading class 'internal'
and when I coment both of them ,I can't get the result from my spellchecker,and when I query a phrase it just spellcheck the the first word of the phrase,what I should do?
I can't see the full component description so I can't say for sure what's going on. If you have more than one spellchecker inside that component make sure it has the same field name.
<str name="field">body-en</str>
The following code works for me:
<searchComponent name="spellcheck" class="solr.SpellCheckComponent">
<lst name="spellchecker">
<str name="name">default</str>
<str name="field">variations</str>
<str name="classname">solr.DirectSolrSpellChecker</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>
</searchComponent>
with the following request handler snippet:
<str name="spellcheck.dictionary">default</str>
<str name="spellcheck">true</str>
<str name="spellcheck.count">3</str>
<str name="spellcheck.onlyMorePopular">true</str>
<str name="spellcheck.extendedResults">true</str>
<str name="spellcheck.collate">true</str>
Hope it helps!
i am trying to use suggeter in my application
example: I have a documents as below
apache solr version 4.2
apache hadoop version 2
cassendra nosql db
mysql rdbms
if i search for "apa" first two result is shown as suggestion and
if the search string is "apache so" only 1st one is shown as suggestion which is as expected
But
if i search for "solr" no result is shown for suggestion( i would expect apache solr version 4.2)
My query is
http://localhost:8983/solr/colletion/suggest?wt=json&indent=true&spellcheck=true&spellcheck.q=solr
below is my field type
<fieldType name="text_general2" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.KeywordTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.KeywordTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
and suggest request handler in solrconfig.xml is
<searchComponent class="solr.SpellCheckComponent" name="suggest">
<lst name="spellchecker">
<str name="name">suggest</str>
<str name="classname">org.apache.solr.spelling.suggest.Suggester</str>
<str name="lookupImpl">org.apache.solr.spelling.suggest.fst.WFSTLookupFactory</str>
<str name="field">title2</str> <!-- the indexed field to derive suggestions from -->
<float name="threshold">0</float>
<str name="buildOnCommit">true</str>
</lst>
</searchComponent>
<requestHandler class="org.apache.solr.handler.component.SearchHandler" name="/suggest">
<lst name="defaults">
<str name="spellcheck">true</str>
<str name="spellcheck.dictionary">suggest</str>
<str name="spellcheck.onlyMorePopular">true</str>
<str name="spellcheck.count">8</str>
<str name="spellcheck.collate">true</str>
</lst>
<arr name="components">
<str>suggest</str>
</arr>
</requestHandler>
my solr version is 4.2 CDH 4.7
please help
You are using a KeywordTokenizerFactory which treats the entire string as a single stream. So in your case, the 1st document would be indexed as
apache solr version 4.2
Since your auto suggest is turned on, your first query apac & others starting with the same prefix apac can match both the entries in index starting with it (as you have suggest turned on)
If you looking to match individual words in a text you should consider using another Tokenizer such as WhitespaceTokenizerFactory.
More details: https://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters#solr.KeywordTokenizerFactory
In solr wiki this phrase can be found:
To enable dynamic core configuration, make sure the adminPath attribute is set in solr.xml. If this attribute is absent, the CoreAdminHandler will not be available.
In old style solr.xml this attribute sets in cores element:
cores adminPath="/admin/cores"
In new (discovery) style solr.xml (available since solr 4.4 and mandatory since coming 5th) there is no cores element to set and no any notion about adminPath attribute around. As a result, if to check localhost:8983/solr, error occurs:
NetworkError: 404 Not Found - http://localhost:8983/solr/admin/cores?wt=json&indexInfo=false
Does all this mean dynamic core handling via HTTP is unavailable in 4.4+ solr or I missed to set something in configs?
Thanks in advance.
Edit solr.xml
<solr>
<str name="adminHandler">${adminHandler:org.apache.solr.handler.admin.CoreAdminHandler}</str>
<int name="coreLoadThreads">${coreLoadThreads:3}</int>
<str name="coreRootDirectory">${coreRootDirectory:#SOLR.CORES.DIRECTORY#}</str>
<str name="managementPath">${managementPath:}</str>
<str name="sharedLib">${sharedLib:}</str>
<str name="shareSchema">${shareSchema:false}</str>
<solrcloud>
<int name="distribUpdateConnTimeout">${distribUpdTimeout:1000000}</int>
<int name="distribUpdateSoTimeout">${distribUpdateTimeout:1000000}</int>
<int name="leaderVoteWait">${leaderVoteWait:1000000}</int>
<str name="host">${host:}</str>
<str name="hostContext">${hostContext:solr}</str>
<int name="hostPort">${jetty.port:8983}</int>
<bool name="genericCoreNodeNames">${genericCoreNodeNames:true}</bool>
</solrcloud>
<logging>
<str name="class">${loggingClass:}</str>
<str name="enabled">${loggingEnabled:}</str>
<watcher>
<int name="size">${loggingSize:1000000}</int>
<int name="threshold">${loggingThreshold:100000}</int>
</watcher>
</logging>
</solr>
I want to configure my Solr search engine so I get an exact match for the search term I enter.
eg. 'taxes' should return documents with 'taxes' and not 'tax', 'taxation' etc.
Any help or tips would be appreciated.
I presume your field is a TextField, by default solr does a fuzzy search on this field. What you want is to set up your field as a string field and add no tokenizer then you'll get an exact match.
You can even combine the exact search with a fuzzy search and use DisMax to boost the relative weights.
Example (schema.xml) :
<field name="name" type="string" indexed="true" stored="false" required="true" />
<field name="nameString" type="string" indexed="true" stored="false" required="true" />
<copyField source="name" dest="nameString"/>
Example (solrconfig.xml) :
<requestHandler name="accounts" class="solr.SearchHandler">
<lst name="defaults">
<str name="defType">dismax</str>
<str name="qf">
nameString^10.0 name^5.0 description^1.0
</str>
<str name="tie">0.1</str>
</lst>
</requestHandler>
To turn off stemming in your schema.xml, you can define text field like this:
<types>
<!-- other fields definition -->
<fieldType name="text_no_stem" class="solr.TextField" omitNorms="false">
<analyzer>
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StandardFilterFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
<!-- other fields definition -->
</types>
<fields>
<!-- other fields definition -->
<dynamicField name="*_nostem" type="text_no_stem" indexed="true" stored="true"/>
<!-- other fields definition -->
</fields>
I'm using sunspot to integrate solr with Ruby on Rails. With this in the schema.xml I define my searchable block like this:
searchable do
text(:wants, as: :wants_nostem)
end
Turn off stemming.
Use the quotes for exact match result :
Example :
core Name : core1
Key : namestring
http://localhost:8983/solr/core1/select?q=namestring:"taxes"&wt=json&indent=true
Use solr string field whcih will do an exact value search e.g
<fieldType class="solr.StrField" name="string" omitNorms="true" sortMissingLast="true" />