mirror of https://github.com/apache/lucene.git
SOLR-648: SpellCheckComponent throws NullPointerException on using spellcheck.q request parameter after restarting Solr, if reload is called but build is not called.
git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@679816 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
feb5d94cab
commit
22cd8ef46f
|
@ -486,6 +486,10 @@ Bug Fixes
|
|||
42. SOLR-616: SpellChecker accuracy configuration is not applied for FileBasedSpellChecker.
|
||||
Apply it for FileBasedSpellChecker and IndexBasedSpellChecker both.
|
||||
(shalin)
|
||||
|
||||
43. SOLR-648: SpellCheckComponent throws NullPointerException on using spellcheck.q request
|
||||
parameter after restarting Solr, if reload is called but build is not called.
|
||||
(Jonathan Lee, shalin)
|
||||
|
||||
Other Changes
|
||||
1. SOLR-135: Moved common classes to org.apache.solr.common and altered the
|
||||
|
|
|
@ -246,7 +246,7 @@ public class SpellCheckComponent extends SearchComponent implements SolrCoreAwar
|
|||
SolrResourceLoader loader = core.getResourceLoader();
|
||||
SolrSpellChecker checker = (SolrSpellChecker) loader.newInstance(className);
|
||||
if (checker != null) {
|
||||
String dictionary = checker.init(spellchecker, loader);
|
||||
String dictionary = checker.init(spellchecker, core);
|
||||
if (dictionary != null) {
|
||||
boolean isDefault = dictionary.equals(SolrSpellChecker.DEFAULT_DICTIONARY_NAME);
|
||||
if (isDefault == true && hasDefault == false){
|
||||
|
|
|
@ -5,8 +5,10 @@ import java.io.IOException;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apache.lucene.analysis.Token;
|
||||
import org.apache.lucene.analysis.WhitespaceAnalyzer;
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.spell.Dictionary;
|
||||
|
@ -17,7 +19,8 @@ import org.apache.lucene.store.Directory;
|
|||
import org.apache.lucene.store.FSDirectory;
|
||||
import org.apache.lucene.store.RAMDirectory;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.core.SolrResourceLoader;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.schema.FieldType;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -30,12 +33,16 @@ import org.apache.solr.core.SolrResourceLoader;
|
|||
* @since solr 1.3
|
||||
*/
|
||||
public abstract class AbstractLuceneSpellChecker extends SolrSpellChecker {
|
||||
public static final Logger LOG = Logger.getLogger(AbstractLuceneSpellChecker.class.getName());
|
||||
|
||||
public static final String SPELLCHECKER_ARG_NAME = "spellchecker";
|
||||
public static final String LOCATION = "sourceLocation";
|
||||
public static final String INDEX_DIR = "spellcheckIndexDir";
|
||||
public static final String ACCURACY = "accuracy";
|
||||
public static final String STRING_DISTANCE = "distanceMeasure";
|
||||
public static final String FIELD_TYPE = "fieldType";
|
||||
protected String field;
|
||||
protected String fieldTypeName;
|
||||
protected org.apache.lucene.search.spell.SpellChecker spellChecker;
|
||||
|
||||
protected String sourceLocation;
|
||||
|
@ -50,14 +57,14 @@ public abstract class AbstractLuceneSpellChecker extends SolrSpellChecker {
|
|||
protected float accuracy = 0.5f;
|
||||
public static final String FIELD = "field";
|
||||
|
||||
public String init(NamedList config, SolrResourceLoader loader) {
|
||||
super.init(config, loader);
|
||||
public String init(NamedList config, SolrCore core) {
|
||||
super.init(config, core);
|
||||
indexDir = (String) config.get(INDEX_DIR);
|
||||
String accuracy = (String) config.get(ACCURACY);
|
||||
//If indexDir is relative then create index inside core.getDataDir()
|
||||
if (indexDir != null) {
|
||||
if (!new File(indexDir).isAbsolute()) {
|
||||
indexDir = loader.getDataDir() + File.separator + indexDir;
|
||||
indexDir = core.getDataDir() + File.separator + indexDir;
|
||||
}
|
||||
}
|
||||
sourceLocation = (String) config.get(LOCATION);
|
||||
|
@ -65,7 +72,7 @@ public abstract class AbstractLuceneSpellChecker extends SolrSpellChecker {
|
|||
String strDistanceName = (String)config.get(STRING_DISTANCE);
|
||||
StringDistance sd = null;
|
||||
if (strDistanceName != null) {
|
||||
sd = (StringDistance) loader.newInstance(strDistanceName);
|
||||
sd = (StringDistance) core.getResourceLoader().newInstance(strDistanceName);
|
||||
//TODO: Figure out how to configure options. Where's Spring when you need it? Or at least BeanUtils...
|
||||
} else {
|
||||
sd = new LevensteinDistance();
|
||||
|
@ -85,6 +92,18 @@ public abstract class AbstractLuceneSpellChecker extends SolrSpellChecker {
|
|||
"Unparseable accuracy given for dictionary: " + name, e);
|
||||
}
|
||||
}
|
||||
if (field != null && core.getSchema().getFieldTypeNoEx(field) != null) {
|
||||
analyzer = core.getSchema().getFieldType(field).getQueryAnalyzer();
|
||||
}
|
||||
fieldTypeName = (String) config.get(FIELD_TYPE);
|
||||
if (core.getSchema().getFieldTypes().containsKey(fieldTypeName)) {
|
||||
FieldType fieldType = core.getSchema().getFieldTypes().get(fieldTypeName);
|
||||
analyzer = fieldType.getQueryAnalyzer();
|
||||
}
|
||||
if (analyzer == null) {
|
||||
LOG.info("Using WhitespaceAnalzyer for dictionary: " + name);
|
||||
analyzer = new WhitespaceAnalyzer();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -132,14 +151,11 @@ public abstract class AbstractLuceneSpellChecker extends SolrSpellChecker {
|
|||
return reader;
|
||||
}
|
||||
|
||||
|
||||
public void reload() throws IOException {
|
||||
spellChecker.setSpellIndex(index);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the {@link #index} variable based on the {@link #indexDir}. Does not actually create the spelling index.
|
||||
*
|
||||
|
|
|
@ -38,7 +38,6 @@ import org.apache.solr.schema.IndexSchema;
|
|||
import org.apache.solr.util.HighFrequencyDictionary;
|
||||
import org.apache.solr.search.SolrIndexSearcher;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A spell checker implementation which can load words from a text
|
||||
|
@ -51,17 +50,13 @@ public class FileBasedSpellChecker extends AbstractLuceneSpellChecker {
|
|||
|
||||
private static final Logger log = Logger.getLogger(FileBasedSpellChecker.class.getName());
|
||||
|
||||
public static final String FIELD_TYPE = "fieldType";
|
||||
|
||||
public static final String SOURCE_FILE_CHAR_ENCODING = "characterEncoding";
|
||||
|
||||
private String fieldTypeName;
|
||||
private String characterEncoding;
|
||||
public static final String WORD_FIELD_NAME = "word";
|
||||
|
||||
public String init(NamedList config, SolrResourceLoader loader) {
|
||||
super.init(config, loader);
|
||||
fieldTypeName = (String) config.get(FIELD_TYPE);
|
||||
public String init(NamedList config, SolrCore core) {
|
||||
super.init(config, core);
|
||||
characterEncoding = (String) config.get(SOURCE_FILE_CHAR_ENCODING);
|
||||
return name;
|
||||
}
|
||||
|
@ -113,12 +108,7 @@ public class FileBasedSpellChecker extends AbstractLuceneSpellChecker {
|
|||
|
||||
dictionary = new HighFrequencyDictionary(IndexReader.open(ramDir),
|
||||
WORD_FIELD_NAME, 0.0f);
|
||||
analyzer = fieldType.getQueryAnalyzer();
|
||||
} else {
|
||||
log.warning("No fieldType: " + fieldTypeName
|
||||
+ " found for dictionary: " + name + ". Using WhitespaceAnalzyer.");
|
||||
analyzer = new WhitespaceAnalyzer();
|
||||
|
||||
// check if character encoding is defined
|
||||
if (characterEncoding == null) {
|
||||
dictionary = new PlainTextDictionary(loader.openResource(sourceLocation));
|
||||
|
|
|
@ -50,8 +50,8 @@ public class IndexBasedSpellChecker extends AbstractLuceneSpellChecker {
|
|||
protected float threshold;
|
||||
protected IndexReader reader;
|
||||
|
||||
public String init(NamedList config, SolrResourceLoader loader) {
|
||||
super.init(config, loader);
|
||||
public String init(NamedList config, SolrCore core) {
|
||||
super.init(config, core);
|
||||
threshold = config.get(THRESHOLD_TOKEN_FREQUENCY) == null ? 0.0f
|
||||
: (Float) config.get(THRESHOLD_TOKEN_FREQUENCY);
|
||||
initSourceReader();
|
||||
|
@ -80,8 +80,9 @@ public class IndexBasedSpellChecker extends AbstractLuceneSpellChecker {
|
|||
reader = this.reader;
|
||||
}
|
||||
|
||||
|
||||
loadLuceneDictionary(core.getSchema(), reader);
|
||||
// Create the dictionary
|
||||
dictionary = new HighFrequencyDictionary(reader, field,
|
||||
threshold);
|
||||
spellChecker.clearIndex();
|
||||
spellChecker.indexDictionary(dictionary);
|
||||
|
||||
|
@ -101,17 +102,6 @@ public class IndexBasedSpellChecker extends AbstractLuceneSpellChecker {
|
|||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void loadLuceneDictionary(IndexSchema schema, IndexReader reader) {
|
||||
// Create the dictionary
|
||||
dictionary = new HighFrequencyDictionary(reader, field,
|
||||
threshold);
|
||||
// Get the field's analyzer
|
||||
FieldType fieldType = schema.getFieldTypeNoEx(field);
|
||||
analyzer = fieldType == null ? new WhitespaceAnalyzer()
|
||||
: fieldType.getQueryAnalyzer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() throws IOException {
|
||||
super.reload();
|
||||
|
|
|
@ -21,7 +21,6 @@ import org.apache.lucene.analysis.Token;
|
|||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.core.SolrResourceLoader;
|
||||
import org.apache.solr.search.SolrIndexSearcher;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -41,7 +40,7 @@ public abstract class SolrSpellChecker {
|
|||
protected String name;
|
||||
protected Analyzer analyzer;
|
||||
|
||||
public String init(NamedList config, SolrResourceLoader loader){
|
||||
public String init(NamedList config, SolrCore core){
|
||||
name = (String) config.get(DICTIONARY_NAME);
|
||||
if (name == null) {
|
||||
name = DEFAULT_DICTIONARY_NAME;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package org.apache.solr.handler.component;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -32,6 +33,7 @@ import org.apache.solr.request.LocalSolrQueryRequest;
|
|||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.request.SolrQueryResponse;
|
||||
import org.apache.solr.request.SolrRequestHandler;
|
||||
import org.apache.solr.spelling.AbstractLuceneSpellChecker;
|
||||
import org.apache.solr.spelling.IndexBasedSpellChecker;
|
||||
import org.apache.solr.util.AbstractSolrTestCase;
|
||||
|
||||
|
@ -311,6 +313,41 @@ public class SpellCheckComponentTest extends AbstractSolrTestCase {
|
|||
"spellcheckerIndexDir was not created inside the configured value for dataDir folder as configured in solrconfig.xml",
|
||||
indexDir.exists());
|
||||
}
|
||||
|
||||
public void testReloadOnStart() throws Exception {
|
||||
assertU(adoc("id", "0", "lowerfilt", "This is a title"));
|
||||
assertU(commit());
|
||||
SolrQueryRequest request = req("qt", "spellCheckCompRH", "q", "*:*",
|
||||
"spellcheck.q", "ttle", "spellcheck", "true", "spellcheck.dictionary",
|
||||
"default", "spellcheck.build", "true");
|
||||
assertQ(request, "//arr[@name='suggestion'][.='title']");
|
||||
|
||||
NamedList args = new NamedList();
|
||||
NamedList spellchecker = new NamedList();
|
||||
spellchecker.add(AbstractLuceneSpellChecker.DICTIONARY_NAME, "default");
|
||||
spellchecker.add(AbstractLuceneSpellChecker.FIELD, "lowerfilt");
|
||||
spellchecker.add(AbstractLuceneSpellChecker.INDEX_DIR, "spellchecker1");
|
||||
args.add("spellchecker", spellchecker);
|
||||
|
||||
SpellCheckComponent checker = new SpellCheckComponent();
|
||||
checker.init(args);
|
||||
checker.inform(h.getCore());
|
||||
|
||||
request = req("qt", "spellCheckCompRH", "q", "*:*", "spellcheck.q", "ttle",
|
||||
"spellcheck", "true", "spellcheck.dictionary", "default",
|
||||
"spellcheck.reload", "true");
|
||||
ResponseBuilder rb = new ResponseBuilder();
|
||||
rb.req = request;
|
||||
rb.rsp = new SolrQueryResponse();
|
||||
rb.components = new ArrayList(h.getCore().getSearchComponents().values());
|
||||
checker.prepare(rb);
|
||||
|
||||
try {
|
||||
checker.process(rb);
|
||||
} catch (NullPointerException e) {
|
||||
fail("NullPointerException due to reload not initializing analyzers");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add more tests for various spelling options
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ public class FileBasedSpellCheckerTest extends AbstractSolrTestCase{
|
|||
indexDir.mkdirs();
|
||||
spellchecker.add(FileBasedSpellChecker.INDEX_DIR, indexDir.getAbsolutePath());
|
||||
SolrCore core = h.getCore();
|
||||
String dictName = checker.init(spellchecker, core.getResourceLoader());
|
||||
String dictName = checker.init(spellchecker, core);
|
||||
assertTrue(dictName + " is not equal to " + "external", dictName.equals("external") == true);
|
||||
checker.build(core, null);
|
||||
|
||||
|
@ -108,7 +108,7 @@ public class FileBasedSpellCheckerTest extends AbstractSolrTestCase{
|
|||
spellchecker.add(FileBasedSpellChecker.FIELD_TYPE, "teststop");
|
||||
spellchecker.add(AbstractLuceneSpellChecker.SPELLCHECKER_ARG_NAME, spellchecker);
|
||||
SolrCore core = h.getCore();
|
||||
String dictName = checker.init(spellchecker, core.getResourceLoader());
|
||||
String dictName = checker.init(spellchecker, core);
|
||||
assertTrue(dictName + " is not equal to " + "external", dictName.equals("external") == true);
|
||||
checker.build(core, null);
|
||||
|
||||
|
@ -149,7 +149,7 @@ public class FileBasedSpellCheckerTest extends AbstractSolrTestCase{
|
|||
spellchecker.add(AbstractLuceneSpellChecker.SPELLCHECKER_ARG_NAME, spellchecker);
|
||||
|
||||
SolrCore core = h.getCore();
|
||||
String dictName = checker.init(spellchecker, core.getResourceLoader());
|
||||
String dictName = checker.init(spellchecker, core);
|
||||
assertTrue(dictName + " is not equal to " + "external", dictName.equals("external") == true);
|
||||
checker.build(core, null);
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ public class IndexBasedSpellCheckerTest extends AbstractSolrTestCase {
|
|||
spellchecker.add(AbstractLuceneSpellChecker.SPELLCHECKER_ARG_NAME, spellchecker);
|
||||
SolrCore core = h.getCore();
|
||||
|
||||
String dictName = checker.init(spellchecker, core.getResourceLoader());
|
||||
String dictName = checker.init(spellchecker, core);
|
||||
assertTrue(dictName + " is not equal to " + SolrSpellChecker.DEFAULT_DICTIONARY_NAME,
|
||||
dictName.equals(SolrSpellChecker.DEFAULT_DICTIONARY_NAME) == true);
|
||||
RefCounted<SolrIndexSearcher> holder = core.getSearcher();
|
||||
|
@ -162,7 +162,7 @@ public class IndexBasedSpellCheckerTest extends AbstractSolrTestCase {
|
|||
spellchecker.add(IndexBasedSpellChecker.FIELD, "title");
|
||||
spellchecker.add(AbstractLuceneSpellChecker.SPELLCHECKER_ARG_NAME, spellchecker);
|
||||
SolrCore core = h.getCore();
|
||||
String dictName = checker.init(spellchecker, core.getResourceLoader());
|
||||
String dictName = checker.init(spellchecker, core);
|
||||
assertTrue(dictName + " is not equal to " + SolrSpellChecker.DEFAULT_DICTIONARY_NAME,
|
||||
dictName.equals(SolrSpellChecker.DEFAULT_DICTIONARY_NAME) == true);
|
||||
RefCounted<SolrIndexSearcher> holder = core.getSearcher();
|
||||
|
@ -218,7 +218,7 @@ public class IndexBasedSpellCheckerTest extends AbstractSolrTestCase {
|
|||
spellchecker.add(AbstractLuceneSpellChecker.SPELLCHECKER_ARG_NAME, spellchecker);
|
||||
spellchecker.add(AbstractLuceneSpellChecker.STRING_DISTANCE, JaroWinklerDistance.class.getName());
|
||||
SolrCore core = h.getCore();
|
||||
String dictName = checker.init(spellchecker, core.getResourceLoader());
|
||||
String dictName = checker.init(spellchecker, core);
|
||||
assertTrue(dictName + " is not equal to " + SolrSpellChecker.DEFAULT_DICTIONARY_NAME,
|
||||
dictName.equals(SolrSpellChecker.DEFAULT_DICTIONARY_NAME) == true);
|
||||
RefCounted<SolrIndexSearcher> holder = core.getSearcher();
|
||||
|
@ -268,7 +268,7 @@ public class IndexBasedSpellCheckerTest extends AbstractSolrTestCase {
|
|||
spellchecker.add(IndexBasedSpellChecker.FIELD, "title");
|
||||
spellchecker.add(AbstractLuceneSpellChecker.SPELLCHECKER_ARG_NAME, spellchecker);
|
||||
SolrCore core = h.getCore();
|
||||
String dictName = checker.init(spellchecker, core.getResourceLoader());
|
||||
String dictName = checker.init(spellchecker, core);
|
||||
assertTrue(dictName + " is not equal to " + SolrSpellChecker.DEFAULT_DICTIONARY_NAME,
|
||||
dictName.equals(SolrSpellChecker.DEFAULT_DICTIONARY_NAME) == true);
|
||||
RefCounted<SolrIndexSearcher> holder = core.getSearcher();
|
||||
|
|
Loading…
Reference in New Issue