mirror of https://github.com/apache/lucene.git
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:
parent
3d73a3014e
commit
85bba7eed7
|
@ -698,6 +698,9 @@ Bug Fixes
|
||||||
* SOLR-3260: DataImportHandler: ScriptTransformer gives better error messages when
|
* SOLR-3260: DataImportHandler: ScriptTransformer gives better error messages when
|
||||||
problems arise on initalization (no Script Engine, invalid script, etc). (James Dyer)
|
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
|
Other Changes
|
||||||
----------------------
|
----------------------
|
||||||
* SOLR-2922: Upgrade commons-io and commons-lang to 2.1 and 2.6, respectively. (koji)
|
* SOLR-2922: Upgrade commons-io and commons-lang to 2.1 and 2.6, respectively. (koji)
|
||||||
|
|
|
@ -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.ParseException;
|
||||||
import org.apache.lucene.queryparser.classic.QueryParser;
|
import org.apache.lucene.queryparser.classic.QueryParser;
|
||||||
import org.apache.lucene.search.*;
|
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.DisMaxParams;
|
||||||
import org.apache.solr.common.params.SolrParams;
|
import org.apache.solr.common.params.SolrParams;
|
||||||
import org.apache.solr.common.util.NamedList;
|
import org.apache.solr.common.util.NamedList;
|
||||||
|
@ -792,8 +793,9 @@ class ExtendedDismaxQParser extends QParser {
|
||||||
String fname = s.substring(pos, p);
|
String fname = s.substring(pos, p);
|
||||||
boolean isInSchema = getReq().getSchema().getFieldTypeNoEx(fname) != null;
|
boolean isInSchema = getReq().getSchema().getFieldTypeNoEx(fname) != null;
|
||||||
boolean isAlias = solrParams.get("f."+fname+".qf") != 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) {
|
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.
|
// literal when we try the escape+re-parse.
|
||||||
if (exceptions) {
|
if (exceptions) {
|
||||||
FieldType ft = schema.getFieldTypeNoEx(field);
|
FieldType ft = schema.getFieldTypeNoEx(field);
|
||||||
if (ft == null) throw unknownField;
|
if (ft == null && null == MagicFieldName.get(field)) {
|
||||||
|
throw unknownField;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return getQuery();
|
return getQuery();
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package org.apache.solr.search;
|
package org.apache.solr.search;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
@ -59,6 +60,33 @@ public class SolrQueryParser extends QueryParser {
|
||||||
protected final QParser parser;
|
protected final QParser parser;
|
||||||
protected final String defaultField;
|
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
|
// implementation detail - caching ReversedWildcardFilterFactory based on type
|
||||||
private Map<FieldType, ReversedWildcardFilterFactory> leadingWildcards;
|
private Map<FieldType, ReversedWildcardFilterFactory> leadingWildcards;
|
||||||
|
|
||||||
|
@ -124,13 +152,12 @@ public class SolrQueryParser extends QueryParser {
|
||||||
checkNullField(field);
|
checkNullField(field);
|
||||||
// intercept magic field name of "_" to use as a hook for our
|
// intercept magic field name of "_" to use as a hook for our
|
||||||
// own functions.
|
// own functions.
|
||||||
if (field.charAt(0) == '_') {
|
if (field.charAt(0) == '_' && parser != null) {
|
||||||
if ("_val_".equals(field)) {
|
MagicFieldName magic = MagicFieldName.get(field);
|
||||||
QParser nested = parser.subQuery(queryText, "func");
|
if (null != magic) {
|
||||||
|
QParser nested = parser.subQuery(queryText, magic.subParser);
|
||||||
return nested.getQuery();
|
return nested.getQuery();
|
||||||
} else if ("_query_".equals(field) && parser != null) {
|
}
|
||||||
return parser.subQuery(queryText, null).getQuery();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
SchemaField sf = schema.getFieldOrNull(field);
|
SchemaField sf = schema.getFieldOrNull(field);
|
||||||
if (sf != null) {
|
if (sf != null) {
|
||||||
|
|
|
@ -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", "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", "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", "50", "text_sw", "start new big city end"));
|
||||||
|
assertU(adoc("id", "51", "store", "12.34,-56.78"));
|
||||||
assertU(commit());
|
assertU(commit());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
@ -66,8 +66,8 @@ public class TestExtendedDismaxParser extends AbstractSolrTestCase {
|
||||||
|
|
||||||
// test the edismax query parser based on the dismax parser
|
// test the edismax query parser based on the dismax parser
|
||||||
public void testFocusQueryParser() {
|
public void testFocusQueryParser() {
|
||||||
String allq = "id:[42 TO 50]";
|
String allq = "id:[42 TO 51]";
|
||||||
String allr = "*[count(//doc)=9]";
|
String allr = "*[count(//doc)=10]";
|
||||||
String oner = "*[count(//doc)=1]";
|
String oner = "*[count(//doc)=1]";
|
||||||
String twor = "*[count(//doc)=2]";
|
String twor = "*[count(//doc)=2]";
|
||||||
String nor = "*[count(//doc)=0]";
|
String nor = "*[count(//doc)=0]";
|
||||||
|
@ -227,6 +227,43 @@ public class TestExtendedDismaxParser extends AbstractSolrTestCase {
|
||||||
|
|
||||||
assertQ(req("defType","edismax", "mm","0", "q","movies_t:Terminator 100", "qf","movies_t foo_i"),
|
assertQ(req("defType","edismax", "mm","0", "q","movies_t:Terminator 100", "qf","movies_t foo_i"),
|
||||||
twor);
|
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
|
/** stopword removal in conjunction with multi-word synonyms at query time
|
||||||
|
|
Loading…
Reference in New Issue