SOLR-4208: ExtendedDismaxQParserPlugin has been refactored to make subclassing easier

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1430399 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Chris M. Hostetter 2013-01-08 17:33:19 +00:00
parent 9ee4b4d5fa
commit 76f5a8bada
5 changed files with 1719 additions and 1382 deletions

View File

@ -569,6 +569,9 @@ Other Changes
* SOLR-4226: Extract fl parsing code out of ReturnFields constructor.
(Ryan Ernst via Robert Muir)
* SOLR-4208: ExtendedDismaxQParserPlugin has been refactored to make
subclassing easier. (Tomás Fernández Löbbe, hossman)
================== 4.0.0 ==================
Versions of Major Components

File diff suppressed because it is too large Load Diff

View File

@ -597,6 +597,7 @@
<!-- unused, for testing luke copyFields -->
<dynamicField name="foo_copysource_*" type="ignored" multiValued="true"/>
<dynamicField name="bar_copydest_*" type="ignored" multiValued="true"/>
<dynamicField name="*_es" type="text" indexed="true" stored="true"/>
</fields>

View File

@ -17,8 +17,21 @@
package org.apache.solr.search;
import java.util.HashSet;
import java.util.Set;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.DisjunctionMaxQuery;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.util.AbstractSolrTestCase;
import org.apache.solr.util.SolrPluginUtils;
import org.junit.BeforeClass;
import org.junit.Test;
@ -510,37 +523,42 @@ public class TestExtendedDismaxParser extends AbstractSolrTestCase {
public void testCyclicAliasing() throws Exception {
try {
h.query(req("defType","edismax", "q","ignore_exception", "qf","who", "f.who.qf","name","f.name.qf","who"));
fail("Simple cyclic alising");
} catch (SolrException e) {
assertTrue(e.getCause().getMessage().contains("Field aliases lead to a cycle"));
}
try {
h.query(req("defType","edismax", "q","ignore_exception", "qf","who", "f.who.qf","name","f.name.qf","myalias", "f.myalias.qf","who"));
fail();
} catch (SolrException e) {
assertTrue(e.getCause().getMessage().contains("Field aliases lead to a cycle"));
}
try {
h.query(req("defType","edismax", "q","ignore_exception", "qf","field1", "f.field1.qf","field2 field3","f.field2.qf","field4 field5", "f.field4.qf","field5", "f.field5.qf","field6", "f.field3.qf","field6"));
} catch (SolrException e) {
fail("This is not cyclic alising");
}
try {
h.query(req("defType","edismax", "q","ignore_exception", "qf","field1", "f.field1.qf","field2 field3", "f.field2.qf","field4 field5", "f.field4.qf","field5", "f.field5.qf","field4"));
fail();
} catch (SolrException e) {
assertTrue(e.getCause().getMessage().contains("Field aliases lead to a cycle"));
}
try {
h.query(req("defType","edismax", "q","who:(Zapp Pig) ignore_exception", "qf","field1", "f.who.qf","name","f.name.qf","myalias", "f.myalias.qf","who"));
fail();
} catch (SolrException e) {
assertTrue(e.getCause().getMessage().contains("Field aliases lead to a cycle"));
ignoreException(".*Field aliases lead to a cycle.*");
try {
h.query(req("defType","edismax", "q","blarg", "qf","who", "f.who.qf","name","f.name.qf","who"));
fail("Simple cyclic alising not detected");
} catch (SolrException e) {
assertTrue(e.getCause().getMessage().contains("Field aliases lead to a cycle"));
}
try {
h.query(req("defType","edismax", "q","blarg", "qf","who", "f.who.qf","name","f.name.qf","myalias", "f.myalias.qf","who"));
fail("Cyclic alising not detected");
} catch (SolrException e) {
assertTrue(e.getCause().getMessage().contains("Field aliases lead to a cycle"));
}
try {
h.query(req("defType","edismax", "q","blarg", "qf","field1", "f.field1.qf","field2 field3","f.field2.qf","field4 field5", "f.field4.qf","field5", "f.field5.qf","field6", "f.field3.qf","field6"));
} catch (SolrException e) {
fail("This is not cyclic alising");
}
try {
h.query(req("defType","edismax", "q","blarg", "qf","field1", "f.field1.qf","field2 field3", "f.field2.qf","field4 field5", "f.field4.qf","field5", "f.field5.qf","field4"));
fail("Cyclic alising not detected");
} catch (SolrException e) {
assertTrue(e.getCause().getMessage().contains("Field aliases lead to a cycle"));
}
try {
h.query(req("defType","edismax", "q","who:(Zapp Pig)", "qf","field1", "f.who.qf","name","f.name.qf","myalias", "f.myalias.qf","who"));
fail("Cyclic alising not detected");
} catch (SolrException e) {
assertTrue(e.getCause().getMessage().contains("Field aliases lead to a cycle"));
}
} finally {
resetExceptionIgnores();
}
}
@ -930,4 +948,157 @@ public class TestExtendedDismaxParser extends AbstractSolrTestCase {
"defType", "edismax")
, "*[count(//doc)=1]");
}
public void testEdismaxSimpleExtension() throws SyntaxError {
ModifiableSolrParams params = new ModifiableSolrParams();
params.set("q", "foo bar");
params.set("qf", "subject title^5");
params.set("qf_fr", "subject_fr title_fr^5");
params.set("qf_en", "subject_en title_en^5");
params.set("qf_es", "subject_es title_es^5");
MultilanguageQueryParser parser = new MultilanguageQueryParser("foo bar", new ModifiableSolrParams(), params, req(params));
Query query = parser.parse();
assertNotNull(query);
assertTrue(containsClause(query, "title", "foo", 5, false));
assertTrue(containsClause(query, "title", "bar", 5, false));
assertTrue(containsClause(query, "subject", "foo", 1, false));
assertTrue(containsClause(query, "subject", "bar", 1, false));
params.set("language", "es");
parser = new MultilanguageQueryParser("foo bar", new ModifiableSolrParams(), params, req(params));
query = parser.parse();
assertNotNull(query);
assertTrue(containsClause(query, "title_es", "foo", 5, false));
assertTrue(containsClause(query, "title_es", "bar", 5, false));
assertTrue(containsClause(query, "subject_es", "foo", 1, false));
assertTrue(containsClause(query, "subject_es", "bar", 1, false));
FuzzyDismaxQParser parser2 = new FuzzyDismaxQParser("foo bar absence", new ModifiableSolrParams(), params, req(params));
query = parser2.parse();
assertNotNull(query);
assertTrue(containsClause(query, "title", "foo", 5, false));
assertTrue(containsClause(query, "title", "bar", 5, false));
assertTrue(containsClause(query, "title", "absence", 5, true));
}
private boolean containsClause(Query query, String field, String value,
int boost, boolean fuzzy) {
if(query instanceof BooleanQuery) {
return containsClause((BooleanQuery)query, field, value, boost, fuzzy);
}
if(query instanceof DisjunctionMaxQuery) {
return containsClause((DisjunctionMaxQuery)query, field, value, boost, fuzzy);
}
if(query instanceof TermQuery && !fuzzy) {
return containsClause((TermQuery)query, field, value, boost);
}
if(query instanceof FuzzyQuery && fuzzy) {
return containsClause((FuzzyQuery)query, field, value, boost);
}
return false;
}
private boolean containsClause(FuzzyQuery query, String field, String value,
int boost) {
if(query.getTerm().field().equals(field) &&
query.getTerm().bytes().utf8ToString().equals(value) &&
query.getBoost() == boost) {
return true;
}
return false;
}
private boolean containsClause(BooleanQuery query, String field, String value, int boost, boolean fuzzy) {
for(BooleanClause clause:query.getClauses()) {
if(containsClause(clause.getQuery(), field, value, boost, fuzzy)) {
return true;
}
}
return false;
}
private boolean containsClause(TermQuery query, String field, String value, int boost) {
if(query.getTerm().field().equals(field) &&
query.getTerm().bytes().utf8ToString().equals(value) &&
query.getBoost() == boost) {
return true;
}
return false;
}
private boolean containsClause(DisjunctionMaxQuery query, String field, String value, int boost, boolean fuzzy) {
for(Query disjunct:query.getDisjuncts()) {
if(containsClause(disjunct, field, value, boost, fuzzy)) {
return true;
}
}
return false;
}
class MultilanguageQueryParser extends ExtendedDismaxQParser {
public MultilanguageQueryParser(String qstr, SolrParams localParams,
SolrParams params, SolrQueryRequest req) {
super(qstr, localParams, params, req);
}
@Override
protected ExtendedDismaxConfiguration createConfiguration(String qstr,
SolrParams localParams, SolrParams params, SolrQueryRequest req) {
return new MultilanguageDismaxConfiguration(localParams, params, req);
}
class MultilanguageDismaxConfiguration extends ExtendedDismaxConfiguration {
public MultilanguageDismaxConfiguration(SolrParams localParams,
SolrParams params, SolrQueryRequest req) {
super(localParams, params, req);
String language = params.get("language");
if(language != null) {
super.queryFields = SolrPluginUtils.parseFieldBoosts(solrParams.getParams("qf_" + language));
}
}
}
}
class FuzzyDismaxQParser extends ExtendedDismaxQParser {
public FuzzyDismaxQParser(String qstr, SolrParams localParams,
SolrParams params, SolrQueryRequest req) {
super(qstr, localParams, params, req);
}
@Override
protected ExtendedSolrQueryParser createEdismaxQueryParser(QParser qParser,
String field) {
return new FuzzyQueryParser(qParser, field);
}
class FuzzyQueryParser extends ExtendedSolrQueryParser{
private Set<String> frequentlyMisspelledWords;
public FuzzyQueryParser(QParser parser, String defaultField) {
super(parser, defaultField);
frequentlyMisspelledWords = new HashSet<String>();
frequentlyMisspelledWords.add("absence");
}
@Override
protected Query getFieldQuery(String field,
String val, boolean quoted) throws SyntaxError {
if(frequentlyMisspelledWords.contains(val)) {
return getFuzzyQuery(field, val, 0.75F);
}
return super.getFieldQuery(field, val, quoted);
}
}
}
}