SOLR-622: SpellCheckComponent supports auto-loading indices on startup and optionally, (re)builds indices on newSearcher event, if configured in solrconfig.xml

git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@681604 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Shalin Shekhar Mangar 2008-08-01 06:11:58 +00:00
parent 258cb3e84d
commit 68083b3af4
4 changed files with 87 additions and 17 deletions

View File

@ -337,6 +337,10 @@ New Features
incremental (delta) indexing. See http://wiki.apache.org/solr/DataImportHandler for more details.
(Noble Paul, shalin)
67. SOLR-622: SpellCheckComponent supports auto-loading indices on startup and optionally, (re)builds indices
on newSearcher event, if configured in solrconfig.xml
(shalin)
Changes in runtime behavior
1. SOLR-559: use Lucene updateDocument, deleteDocuments methods. This
removes the maxBufferedDeletes parameter added by SOLR-310 as Lucene

View File

@ -17,10 +17,24 @@
package org.apache.solr.handler.component;
import org.apache.lucene.analysis.Token;
import org.apache.lucene.analysis.WhitespaceAnalyzer;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.xpath.XPathConstants;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.Token;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.WhitespaceAnalyzer;
import org.apache.lucene.index.IndexReader;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CommonParams;
@ -30,29 +44,21 @@ import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.core.SolrConfig;
import org.apache.solr.core.SolrCore;
import org.apache.solr.core.SolrEventListener;
import org.apache.solr.core.SolrResourceLoader;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.spelling.AbstractLuceneSpellChecker;
import org.apache.solr.spelling.IndexBasedSpellChecker;
import org.apache.solr.spelling.QueryConverter;
import org.apache.solr.spelling.SolrSpellChecker;
import org.apache.solr.spelling.SpellingResult;
import org.apache.solr.spelling.QueryConverter;
import org.apache.solr.util.RefCounted;
import org.apache.solr.util.plugin.NamedListPluginLoader;
import org.apache.solr.util.plugin.SolrCoreAware;
import org.w3c.dom.NodeList;
import javax.xml.xpath.XPathConstants;
import java.io.IOException;
import java.io.StringReader;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
/**
* A SearchComponent implementation which provides support for spell checking
* and suggestions using the Lucene contributed SpellChecker.
@ -263,6 +269,12 @@ public class SpellCheckComponent extends SearchComponent implements SolrCoreAwar
throw new RuntimeException("More than one dictionary is missing name.");
}
}
// Register event listeners for this SpellChecker
core.registerFirstSearcherListener(new SpellCheckerListener(core, checker, true));
if (Boolean.parseBoolean((String)spellchecker.get("buildOnCommit"))) {
LOG.info("Registering newSearcher listener for spellchecker: " + checker.getDictionaryName());
core.registerNewSearcherListener(new SpellCheckerListener(core, checker, false));
}
} else {
throw new RuntimeException("Can't load spell checker: " + className);
}
@ -294,6 +306,47 @@ public class SpellCheckComponent extends SearchComponent implements SolrCoreAwar
}
}
private static class SpellCheckerListener implements SolrEventListener {
private final SolrCore core;
private final SolrSpellChecker checker;
private final boolean firstSearcher;
public SpellCheckerListener(SolrCore core, SolrSpellChecker checker, boolean firstSearcher) {
this.core = core;
this.checker = checker;
this.firstSearcher = firstSearcher;
}
public void init(NamedList args) {
}
public void newSearcher(SolrIndexSearcher newSearcher,
SolrIndexSearcher currentSearcher) {
if (firstSearcher) {
try {
LOG.info("Loading spell index for spellchecker: "
+ checker.getDictionaryName());
checker.reload();
} catch (IOException e) {
LOG.log(Level.SEVERE, "Exception in reloading spell check index for spellchecker: " + checker.getDictionaryName(), e);
}
} else {
// newSearcher event
try {
LOG.info("Building spell index for spell checker: " + checker.getDictionaryName());
checker.build(core, newSearcher);
} catch (Exception e) {
LOG.log(Level.SEVERE,
"Exception in building spell check index for spellchecker: " + checker.getDictionaryName(), e);
}
}
}
public void postCommit() {
}
}
// ///////////////////////////////////////////
// / SolrInfoMBean
// //////////////////////////////////////////

View File

@ -349,6 +349,18 @@ public class SpellCheckComponentTest extends AbstractSolrTestCase {
}
}
@SuppressWarnings("unchecked")
public void testRebuildOnCommit() throws Exception {
SolrQueryRequest req = req("q", "lowerfilt:lucenejavt", "qt", "spellCheckCompRH", "spellcheck", "true");
String response = h.query(req);
assertFalse("No suggestions should be returned", response.contains("lucenejava"));
assertU(adoc("id", "11231", "lowerfilt", "lucenejava"));
assertU("commit", commit());
assertQ(req, "//arr[@name='suggestion'][.='lucenejava']");
}
// TODO: add more tests for various spelling options
}

View File

@ -326,6 +326,7 @@
<str name="name">default</str>
<str name="field">lowerfilt</str>
<str name="spellcheckIndexDir">spellchecker1</str>
<str name="buildOnCommit">true</str>
</lst>
<!-- Example of using different distance measure -->
<lst name="spellchecker">