SOLR-2959: edismax now respects the magic fields '_val_' and '_query_'

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1303256 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Chris M. Hostetter 2012-03-21 02:32:48 +00:00
parent 3d73a3014e
commit 85bba7eed7
4 changed files with 82 additions and 11 deletions

View File

@ -698,6 +698,9 @@ Bug Fixes
* SOLR-3260: DataImportHandler: ScriptTransformer gives better error messages when
problems arise on initalization (no Script Engine, invalid script, etc). (James Dyer)
* SOLR-2959: edismax now respects the magic fields '_val_' and '_query_'
(Michael Watts, hossman)
Other Changes
----------------------
* SOLR-2922: Upgrade commons-io and commons-lang to 2.1 and 2.6, respectively. (koji)

View File

@ -40,6 +40,7 @@ import org.apache.lucene.queries.function.valuesource.QueryValueSource;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.solr.search.SolrQueryParser.MagicFieldName;
import org.apache.solr.common.params.DisMaxParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
@ -792,8 +793,9 @@ class ExtendedDismaxQParser extends QParser {
String fname = s.substring(pos, p);
boolean isInSchema = getReq().getSchema().getFieldTypeNoEx(fname) != null;
boolean isAlias = solrParams.get("f."+fname+".qf") != null;
boolean isMagic = (null != MagicFieldName.get(fname));
return (isInSchema || isAlias) ? fname : null;
return (isInSchema || isAlias || isMagic) ? fname : null;
}
public static List<String> split(String s, boolean ignoreQuote) {
@ -1082,7 +1084,9 @@ class ExtendedDismaxQParser extends QParser {
// literal when we try the escape+re-parse.
if (exceptions) {
FieldType ft = schema.getFieldTypeNoEx(field);
if (ft == null) throw unknownField;
if (ft == null && null == MagicFieldName.get(field)) {
throw unknownField;
}
}
return getQuery();

View File

@ -17,6 +17,7 @@
package org.apache.solr.search;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
@ -59,6 +60,33 @@ public class SolrQueryParser extends QueryParser {
protected final QParser parser;
protected final String defaultField;
/**
* Identifies the list of all known "magic fields" that trigger
* special parsing behavior
*/
public static enum MagicFieldName {
VAL("_val_", "func"), QUERY("_query_", null);
public final String field;
public final String subParser;
MagicFieldName(final String field, final String subParser) {
this.field = field;
this.subParser = subParser;
}
public String toString() {
return field;
}
private final static Map<String,MagicFieldName> lookup
= new HashMap<String,MagicFieldName>();
static {
for(MagicFieldName s : EnumSet.allOf(MagicFieldName.class))
lookup.put(s.toString(), s);
}
public static MagicFieldName get(final String field) {
return lookup.get(field);
}
}
// implementation detail - caching ReversedWildcardFilterFactory based on type
private Map<FieldType, ReversedWildcardFilterFactory> leadingWildcards;
@ -124,12 +152,11 @@ public class SolrQueryParser extends QueryParser {
checkNullField(field);
// intercept magic field name of "_" to use as a hook for our
// own functions.
if (field.charAt(0) == '_') {
if ("_val_".equals(field)) {
QParser nested = parser.subQuery(queryText, "func");
if (field.charAt(0) == '_' && parser != null) {
MagicFieldName magic = MagicFieldName.get(field);
if (null != magic) {
QParser nested = parser.subQuery(queryText, magic.subParser);
return nested.getQuery();
} else if ("_query_".equals(field) && parser != null) {
return parser.subQuery(queryText, null).getQuery();
}
}
SchemaField sf = schema.getFieldOrNull(field);

View File

@ -54,7 +54,7 @@ public class TestExtendedDismaxParser extends AbstractSolrTestCase {
assertU(adoc("id", "48", "text_sw", "this has gigabyte potential", "foo_i","100"));
assertU(adoc("id", "49", "text_sw", "start the big apple end", "foo_i","-100"));
assertU(adoc("id", "50", "text_sw", "start new big city end"));
assertU(adoc("id", "51", "store", "12.34,-56.78"));
assertU(commit());
}
@Override
@ -66,8 +66,8 @@ public class TestExtendedDismaxParser extends AbstractSolrTestCase {
// test the edismax query parser based on the dismax parser
public void testFocusQueryParser() {
String allq = "id:[42 TO 50]";
String allr = "*[count(//doc)=9]";
String allq = "id:[42 TO 51]";
String allr = "*[count(//doc)=10]";
String oner = "*[count(//doc)=1]";
String twor = "*[count(//doc)=2]";
String nor = "*[count(//doc)=0]";
@ -228,6 +228,43 @@ public class TestExtendedDismaxParser extends AbstractSolrTestCase {
assertQ(req("defType","edismax", "mm","0", "q","movies_t:Terminator 100", "qf","movies_t foo_i"),
twor);
// special psuedo-fields like _query_ and _val_
// special fields (and real field id) should be included by default
assertQ(req("defType", "edismax",
"mm", "100%",
"fq", "id:51",
"q", "_query_:\"{!geofilt d=20 sfield=store pt=12.34,-56.78}\""),
oner);
// should also work when explicitly allowed
assertQ(req("defType", "edismax",
"mm", "100%",
"fq", "id:51",
"uf", "id _query_",
"q", "_query_:\"{!geofilt d=20 sfield=store pt=12.34,-56.78}\""),
oner);
assertQ(req("defType", "edismax",
"mm", "100%",
"fq", "id:51",
"uf", "id",
"uf", "_query_",
"q", "_query_:\"{!geofilt d=20 sfield=store pt=12.34,-56.78}\""),
oner);
// should fail when prohibited
assertQ(req("defType", "edismax",
"mm", "100%",
"fq", "id:51",
"uf", "* -_query_", // explicitly excluded
"q", "_query_:\"{!geofilt d=20 sfield=store pt=12.34,-56.78}\""),
nor);
assertQ(req("defType", "edismax",
"mm", "100%",
"fq", "id:51",
"uf", "id", // excluded by ommision
"q", "_query_:\"{!geofilt d=20 sfield=store pt=12.34,-56.78}\""),
nor);
/** stopword removal in conjunction with multi-word synonyms at query time
* break this test.