SOLR-10423: Disable graph query production via schema configuration <fieldtype ... enableGraphQueries="false">. This fixes broken queries for ShingleFilter-containing query-time analyzers when request param sow=false.

This commit is contained in:
Steve Rowe 2017-04-05 16:23:26 -04:00
parent ef8126e5ea
commit dbd22a6ada
10 changed files with 90 additions and 16 deletions

View File

@ -215,6 +215,10 @@ Bug Fixes
* SOLR-10404: The fetch() streaming expression wouldn't work if a value included query syntax chars (like :+-).
Fixed, and enhanced the generated query to not pollute the queryCache. (David Smiley)
* SOLR-10423: Disable graph query production via schema configuration <fieldtype ... enableGraphQueries="false">.
This fixes broken queries for ShingleFilter-containing query-time analyzers when request param sow=false.
(Steve Rowe)
================== 6.5.0 ==================

View File

@ -52,12 +52,13 @@ public class QueryParser extends SolrQueryParserBase implements QueryParserConst
@Override
protected Query newFieldQuery(Analyzer analyzer, String field, String queryText,
boolean quoted, boolean fieldAutoGenPhraseQueries) throws SyntaxError {
boolean quoted, boolean fieldAutoGenPhraseQueries, boolean fieldEnableGraphQueries)
throws SyntaxError {
setAutoGenerateMultiTermSynonymsPhraseQuery(fieldAutoGenPhraseQueries || getAutoGeneratePhraseQueries());
// Don't auto-quote graph-aware field queries
boolean treatAsQuoted = getSplitOnWhitespace()
? (quoted || fieldAutoGenPhraseQueries || getAutoGeneratePhraseQueries()) : quoted;
return super.newFieldQuery(analyzer, field, queryText, treatAsQuoted, false);
return super.newFieldQuery(analyzer, field, queryText, treatAsQuoted, false, fieldEnableGraphQueries);
}
// * Query ::= ( Clause )*

View File

@ -76,12 +76,13 @@ public class QueryParser extends SolrQueryParserBase {
@Override
protected Query newFieldQuery(Analyzer analyzer, String field, String queryText,
boolean quoted, boolean fieldAutoGenPhraseQueries) throws SyntaxError {
boolean quoted, boolean fieldAutoGenPhraseQueries, boolean fieldEnableGraphQueries)
throws SyntaxError {
setAutoGenerateMultiTermSynonymsPhraseQuery(fieldAutoGenPhraseQueries || getAutoGeneratePhraseQueries());
// Don't auto-quote graph-aware field queries
boolean treatAsQuoted = getSplitOnWhitespace()
? (quoted || fieldAutoGenPhraseQueries || getAutoGeneratePhraseQueries()) : quoted;
return super.newFieldQuery(analyzer, field, queryText, treatAsQuoted, false);
return super.newFieldQuery(analyzer, field, queryText, treatAsQuoted, false, fieldEnableGraphQueries);
}
}

View File

@ -437,10 +437,14 @@ public abstract class SolrQueryParserBase extends QueryBuilder {
}
protected Query newFieldQuery(Analyzer analyzer, String field, String queryText,
boolean quoted, boolean fieldAutoGenPhraseQueries) throws SyntaxError {
boolean quoted, boolean fieldAutoGenPhraseQueries, boolean fieldEnableGraphQueries)
throws SyntaxError {
BooleanClause.Occur occur = operator == Operator.AND ? BooleanClause.Occur.MUST : BooleanClause.Occur.SHOULD;
return createFieldQuery(analyzer, occur, field, queryText,
setEnableGraphQueries(fieldEnableGraphQueries);
Query query = createFieldQuery(analyzer, occur, field, queryText,
quoted || fieldAutoGenPhraseQueries || autoGeneratePhraseQueries, phraseSlop);
setEnableGraphQueries(true); // reset back to default
return query;
}
@ -632,8 +636,10 @@ public abstract class SolrQueryParserBase extends QueryBuilder {
Query subq;
if (ft.isTokenized() && sfield.indexed()) {
boolean fieldAutoGenPhraseQueries = ft instanceof TextField && ((TextField)ft).getAutoGeneratePhraseQueries();
boolean fieldEnableGraphQueries = ft instanceof TextField && ((TextField)ft).getEnableGraphQueries();
subq = newFieldQuery(getAnalyzer(), sfield.getName(), rawq.getJoinedExternalVal(),
false, fieldAutoGenPhraseQueries);
false, fieldAutoGenPhraseQueries, fieldEnableGraphQueries);
booleanBuilder.add(subq, BooleanClause.Occur.SHOULD);
} else {
for (String externalVal : rawq.getExternalVals()) {
@ -949,7 +955,8 @@ public abstract class SolrQueryParserBase extends QueryBuilder {
// delegate to type for everything except tokenized fields
if (ft.isTokenized() && sf.indexed()) {
boolean fieldAutoGenPhraseQueries = ft instanceof TextField && ((TextField)ft).getAutoGeneratePhraseQueries();
return newFieldQuery(getAnalyzer(), field, queryText, quoted, fieldAutoGenPhraseQueries);
boolean fieldEnableGraphQueries = ft instanceof TextField && ((TextField)ft).getEnableGraphQueries();
return newFieldQuery(getAnalyzer(), field, queryText, quoted, fieldAutoGenPhraseQueries, fieldEnableGraphQueries);
} else {
if (raw) {
return new RawQuery(sf, queryText);
@ -960,7 +967,7 @@ public abstract class SolrQueryParserBase extends QueryBuilder {
}
// default to a normal field query
return newFieldQuery(getAnalyzer(), field, queryText, quoted, false);
return newFieldQuery(getAnalyzer(), field, queryText, quoted, false, true);
}
// Assumption: quoted is always false
@ -993,7 +1000,9 @@ public abstract class SolrQueryParserBase extends QueryBuilder {
if (ft.isTokenized() && sf.indexed()) {
String queryText = queryTerms.size() == 1 ? queryTerms.get(0) : String.join(" ", queryTerms);
boolean fieldAutoGenPhraseQueries = ft instanceof TextField && ((TextField)ft).getAutoGeneratePhraseQueries();
return newFieldQuery(getAnalyzer(), field, queryText, false, fieldAutoGenPhraseQueries);
boolean fieldEnableGraphQueries = ft instanceof TextField && ((TextField)ft).getEnableGraphQueries();
return newFieldQuery
(getAnalyzer(), field, queryText, false, fieldAutoGenPhraseQueries, fieldEnableGraphQueries);
} else {
if (raw) {
return new RawQuery(sf, queryTerms);
@ -1025,7 +1034,7 @@ public abstract class SolrQueryParserBase extends QueryBuilder {
// default to a normal field query
String queryText = queryTerms.size() == 1 ? queryTerms.get(0) : String.join(" ", queryTerms);
return newFieldQuery(getAnalyzer(), field, queryText, false, false);
return newFieldQuery(getAnalyzer(), field, queryText, false, false, true);
}
protected boolean isRangeShouldBeProtectedFromReverse(String field, String part1){

View File

@ -833,7 +833,8 @@ public abstract class FieldType extends FieldProperties {
private static final String POSTINGS_FORMAT = "postingsFormat";
private static final String DOC_VALUES_FORMAT = "docValuesFormat";
private static final String AUTO_GENERATE_PHRASE_QUERIES = "autoGeneratePhraseQueries";
protected static final String AUTO_GENERATE_PHRASE_QUERIES = "autoGeneratePhraseQueries";
protected static final String ENABLE_GRAPH_QUERIES = "enableGraphQueries";
private static final String ARGS = "args";
private static final String POSITION_INCREMENT_GAP = "positionIncrementGap";
@ -856,6 +857,7 @@ public abstract class FieldType extends FieldProperties {
}
if (this instanceof TextField) {
namedPropertyValues.add(AUTO_GENERATE_PHRASE_QUERIES, ((TextField) this).getAutoGeneratePhraseQueries());
namedPropertyValues.add(ENABLE_GRAPH_QUERIES, ((TextField) this).getEnableGraphQueries());
}
namedPropertyValues.add(getPropertyName(INDEXED), hasProperty(INDEXED));
namedPropertyValues.add(getPropertyName(STORED), hasProperty(STORED));

View File

@ -41,6 +41,7 @@ import org.apache.solr.uninverting.UninvertingReader.Type;
*/
public class TextField extends FieldType {
protected boolean autoGeneratePhraseQueries;
protected boolean enableGraphQueries;
/**
* Analyzer set by schema for text types to use when searching fields
@ -69,9 +70,15 @@ public class TextField extends FieldType {
} else {
autoGeneratePhraseQueries = true;
}
String autoGeneratePhraseQueriesStr = args.remove("autoGeneratePhraseQueries");
String autoGeneratePhraseQueriesStr = args.remove(AUTO_GENERATE_PHRASE_QUERIES);
if (autoGeneratePhraseQueriesStr != null)
autoGeneratePhraseQueries = Boolean.parseBoolean(autoGeneratePhraseQueriesStr);
enableGraphQueries = true;
String enableGraphQueriesStr = args.remove(ENABLE_GRAPH_QUERIES);
if (enableGraphQueriesStr != null)
enableGraphQueries = Boolean.parseBoolean(enableGraphQueriesStr);
super.init(schema, args);
}
@ -93,6 +100,10 @@ public class TextField extends FieldType {
public boolean getAutoGeneratePhraseQueries() {
return autoGeneratePhraseQueries;
}
public boolean getEnableGraphQueries() {
return enableGraphQueries;
}
@Override
public SortField getSortField(SchemaField field, boolean reverse) {

View File

@ -1080,7 +1080,8 @@ public class ExtendedDismaxQParser extends QParser {
@Override
protected Query newFieldQuery(Analyzer analyzer, String field, String queryText,
boolean quoted, boolean fieldAutoGenPhraseQueries) throws SyntaxError {
boolean quoted, boolean fieldAutoGenPhraseQueries, boolean enableGraphQueries)
throws SyntaxError {
Analyzer actualAnalyzer;
if (removeStopFilter) {
if (nonStopFilterAnalyzerPerField == null) {
@ -1093,7 +1094,7 @@ public class ExtendedDismaxQParser extends QParser {
} else {
actualAnalyzer = parser.getReq().getSchema().getFieldType(field).getQueryAnalyzer();
}
return super.newFieldQuery(actualAnalyzer, field, queryText, quoted, fieldAutoGenPhraseQueries);
return super.newFieldQuery(actualAnalyzer, field, queryText, quoted, fieldAutoGenPhraseQueries, enableGraphQueries);
}
@Override

View File

@ -467,7 +467,14 @@
<fieldType name="currency" class="solr.CurrencyField" currencyConfig="currency.xml" multiValued="false"/>
<fieldType name="shingle23" class="solr.TextField" enableGraphQueries="false" multiValued="true">
<analyzer>
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.ShingleFilterFactory" minShingleSize="2" maxShingleSize="3"
tokenSeparator="_" outputUnigrams="false"/>
</analyzer>
</fieldType>
<field name="id" type="string" indexed="true" stored="true" multiValued="false" required="true"/>
<field name="signatureField" type="string" indexed="true" stored="false"/>
<field name="uuid" type="uuid" stored="true"/>
@ -568,6 +575,8 @@
<field name="uniq2" type="string" indexed="true" stored="true" multiValued="true"/>
<field name="uniq3" type="string" indexed="true" stored="true"/>
<field name="nouniq" type="string" indexed="true" stored="true" multiValued="true"/>
<field name="shingle23" type="shingle23" indexed="true" stored="true"/>
<!--

View File

@ -93,6 +93,7 @@ public class TestExtendedDismaxParser extends SolrTestCaseJ4 {
assertU(adoc("id", "70", "text_sw", "hair"));
assertU(adoc("id", "71", "text_sw", "ties"));
assertU(adoc("id", "72", "text_sw", "wifi ATM"));
assertU(adoc("id", "73", "shingle23", "A B X D E"));
assertU(commit());
}
@ -1946,4 +1947,21 @@ public class TestExtendedDismaxParser extends SolrTestCaseJ4 {
}
}
}
@Test
public void testShingleQueries() throws Exception {
ModifiableSolrParams params = new ModifiableSolrParams();
params.add("sow", "false");
params.add("defType", "edismax");
try (SolrQueryRequest req = req(params)) {
QParser qParser = QParser.getParser("shingle23:(A B C)", req);
Query q = qParser.getQuery();
assertEquals("Synonym(shingle23:A_B shingle23:A_B_C) shingle23:B_C", q.toString());
}
assertJQ(req("df", "shingle23", "q", "A B C", "sow", "false")
, "/response/numFound==1"
);
}
}

View File

@ -67,6 +67,8 @@ public class TestSolrQueryParser extends SolrTestCaseJ4 {
assertU(adoc("id", "13", "eee_s", "'balance'", "rrr_s", "/leading_slash"));
assertU(adoc("id", "20", "syn", "wifi ATM"));
assertU(adoc("id", "30", "shingle23", "A B X D E"));
assertU(commit());
}
@ -995,4 +997,20 @@ public class TestSolrQueryParser extends SolrTestCaseJ4 {
}
}
}
@Test
public void testShingleQueries() throws Exception {
ModifiableSolrParams sowFalseParams = new ModifiableSolrParams();
sowFalseParams.add("sow", "false");
try (SolrQueryRequest req = req(sowFalseParams)) {
QParser qParser = QParser.getParser("shingle23:(A B C)", req);
Query q = qParser.getQuery();
assertEquals("Synonym(shingle23:A_B shingle23:A_B_C) shingle23:B_C", q.toString());
}
assertJQ(req("df", "shingle23", "q", "A B C", "sow", "false")
, "/response/numFound==1"
);
}
}