SOLR-10584: Remove defaultOperator completely in 7.0

This commit is contained in:
Jan Høydahl 2017-05-15 09:44:09 +02:00
parent 9dc952a47c
commit 66cd20e98a
16 changed files with 72 additions and 130 deletions

View File

@ -70,6 +70,9 @@ Upgrading from Solr 6.x
query text will not be split on whitespace before analysis. See query text will not be split on whitespace before analysis. See
https://lucidworks.com/2017/04/18/multi-word-synonyms-solr-adds-query-time-support/ . https://lucidworks.com/2017/04/18/multi-word-synonyms-solr-adds-query-time-support/ .
* Setting <solrQueryParser defaultOperator="..."/> in schema is no longer allowed and will cause an exception.
Please use "q.op" parameter on the request instead. For more details, see SOLR-10584.
New Features New Features
---------------------- ----------------------
* SOLR-9857, SOLR-9858: Collect aggregated metrics from nodes and shard leaders in overseer. (ab) * SOLR-9857, SOLR-9858: Collect aggregated metrics from nodes and shard leaders in overseer. (ab)
@ -102,7 +105,7 @@ Bug Fixes
* SOLR-10408: v2 API introspect should return useful message for non-existent command (Cao Manh Dat) * SOLR-10408: v2 API introspect should return useful message for non-existent command (Cao Manh Dat)
* SOLR-10411: v2 Collection API "modify" command specification's replicationFactor property is incorrectly typed as string, * SOLR-10411: v2 Collection API "modify" command specification's replicationFactor property is incorrectly typed as string,
should be integer (Cao Manh Dat) should be integer (Cao Manh Dat)
* SOLR-10405: v2 API introspect response contains multiple copies of the experimental format WARNING (Cao Manh Dat) * SOLR-10405: v2 API introspect response contains multiple copies of the experimental format WARNING (Cao Manh Dat)
@ -128,6 +131,7 @@ Optimizations
(yonik) (yonik)
Other Changes Other Changes
----------------------
* SOLR-10236: Removed FieldType.getNumericType(). Use getNumberType() instead. (Tomás Fernández Löbbe) * SOLR-10236: Removed FieldType.getNumericType(). Use getNumberType() instead. (Tomás Fernández Löbbe)
* SOLR-10347: Removed index level boost support from "documents" section of the admin UI (Amrit Sarkar via * SOLR-10347: Removed index level boost support from "documents" section of the admin UI (Amrit Sarkar via
@ -148,6 +152,9 @@ Other Changes
* SOLR-10647: Move the V1 <-> V2 API mapping to SolrJ (noble) * SOLR-10647: Move the V1 <-> V2 API mapping to SolrJ (noble)
* SOLR-10584: We'll now always throw an exception if defaultOperator is found in schema. This config has
been deprecated since 3.6, and enforced for new configs since 6.6 (janhoy)
================== 6.7.0 ================== ================== 6.7.0 ==================
Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release. Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release.
@ -169,8 +176,8 @@ Other Changes
* SOLR-10617: JDBCStream accepts columns of type TIME, DATE & TIMESTAMP as well as CLOBs and decimal * SOLR-10617: JDBCStream accepts columns of type TIME, DATE & TIMESTAMP as well as CLOBs and decimal
numeric types (James Dyer) numeric types (James Dyer)
* SOLR-10400: Replace (instanceof TrieFooField || instanceof FooPointField) constructs with * SOLR-10400: Replace (instanceof TrieFooField || instanceof FooPointField) constructs with
FieldType.getNumberType() or SchemaField.getSortField() where appropriate. (hossman, Steve Rowe) FieldType.getNumberType() or SchemaField.getSortField() where appropriate. (hossman, Steve Rowe)
================== 6.6.0 ================== ================== 6.6.0 ==================
@ -361,9 +368,9 @@ Bug Fixes
* SOLR-10549: The new 'large' attribute had been forgotten in /schema/fieldtypes?showDefaults=true (David Smiley) * SOLR-10549: The new 'large' attribute had been forgotten in /schema/fieldtypes?showDefaults=true (David Smiley)
* SOLR-10615: requests are suspended until SolrDispatchFilter initialization is completed. * SOLR-10615: requests are suspended until SolrDispatchFilter initialization is completed.
After core container shutdown or severe initialization problem Solr responds with After core container shutdown or severe initialization problem Solr responds with
http stauts 404 Not Found instead of 500 as it was before (Mikhail Khludnev) http stauts 404 Not Found instead of 500 as it was before (Mikhail Khludnev)
* SOLR-8149: Admin UI - Plugins / Stats - active item is now highlighted (Labuzov Dmitriy via janhoy) * SOLR-8149: Admin UI - Plugins / Stats - active item is now highlighted (Labuzov Dmitriy via janhoy)
@ -438,9 +445,9 @@ Other Changes
* SOLR-10601: StreamExpressionParser should handle white space around = in named parameters (Joel Bernstein) * SOLR-10601: StreamExpressionParser should handle white space around = in named parameters (Joel Bernstein)
* SOLR-10614: Static fields have turned to instance's field in SimplePostTool. * SOLR-10614: Static fields have turned to instance's field in SimplePostTool.
Enabled TestSolrCLIRunExample.testTechproductsExample(). (Andrey Kudryavtsev, Mikhail Khludnev) Enabled TestSolrCLIRunExample.testTechproductsExample(). (Andrey Kudryavtsev, Mikhail Khludnev)
* SOLR-10522: Revert SpellCheckComponent response format change from SOLR-9972 (rel. 6.5.0). While this * SOLR-10522: Revert SpellCheckComponent response format change from SOLR-9972 (rel. 6.5.0). While this
was an improvement for the json "arrntv" format, it caused problems for the default json format. was an improvement for the json "arrntv" format, it caused problems for the default json format.
(James Dyer, reported by Nikita Pchelintsev) (James Dyer, reported by Nikita Pchelintsev)

View File

@ -146,12 +146,6 @@ public class SchemaHandler extends RequestHandlerBase implements SolrCoreAware,
rsp.add(IndexSchema.DEFAULT_SEARCH_FIELD, defaultSearchFieldName); rsp.add(IndexSchema.DEFAULT_SEARCH_FIELD, defaultSearchFieldName);
break; break;
} }
case "/schema/solrqueryparser": {
SimpleOrderedMap<Object> props = new SimpleOrderedMap<>();
props.add(IndexSchema.DEFAULT_OPERATOR, req.getSchema().getQueryParserDefaultOperator());
rsp.add(IndexSchema.SOLR_QUERY_PARSER, props);
break;
}
case "/schema/zkversion": { case "/schema/zkversion": {
int refreshIfBelowVersion = -1; int refreshIfBelowVersion = -1;
Object refreshParam = req.getParams().get("refreshIfBelowVersion"); Object refreshParam = req.getParams().get("refreshIfBelowVersion");
@ -175,10 +169,6 @@ public class SchemaHandler extends RequestHandlerBase implements SolrCoreAware,
rsp.add("zkversion", zkVersion); rsp.add("zkversion", zkVersion);
break; break;
} }
case "/schema/solrqueryparser/defaultoperator": {
rsp.add(IndexSchema.DEFAULT_OPERATOR, req.getSchema().getQueryParserDefaultOperator());
break;
}
default: { default: {
List<String> parts = StrUtils.splitSmart(path, '/'); List<String> parts = StrUtils.splitSmart(path, '/');
if (parts.get(0).isEmpty()) parts.remove(0); if (parts.get(0).isEmpty()) parts.remove(0);

View File

@ -103,10 +103,6 @@ public class SchemaXmlWriter extends TextResponseWriter {
closeStartTag(false); closeStartTag(false);
writer.write(val.toString()); writer.write(val.toString());
endTag(IndexSchema.DEFAULT_SEARCH_FIELD, false); endTag(IndexSchema.DEFAULT_SEARCH_FIELD, false);
} else if (schemaPropName.equals(IndexSchema.SOLR_QUERY_PARSER)) {
openStartTag(IndexSchema.SOLR_QUERY_PARSER);
writeAttr(IndexSchema.DEFAULT_OPERATOR, ((Map<String ,Object>) val).get(IndexSchema.DEFAULT_OPERATOR).toString());
closeStartTag(true);
} else if (schemaPropName.equals(IndexSchema.SIMILARITY)) { } else if (schemaPropName.equals(IndexSchema.SIMILARITY)) {
writeSimilarity((SimpleOrderedMap<Object>) val); writeSimilarity((SimpleOrderedMap<Object>) val);
} else if (schemaPropName.equals(IndexSchema.FIELD_TYPES)) { } else if (schemaPropName.equals(IndexSchema.FIELD_TYPES)) {

View File

@ -94,7 +94,6 @@ import static java.util.Collections.singletonMap;
public class IndexSchema { public class IndexSchema {
public static final String COPY_FIELD = "copyField"; public static final String COPY_FIELD = "copyField";
public static final String COPY_FIELDS = COPY_FIELD + "s"; public static final String COPY_FIELDS = COPY_FIELD + "s";
public static final String DEFAULT_OPERATOR = "defaultOperator";
public static final String DEFAULT_SCHEMA_FILE = "schema.xml"; public static final String DEFAULT_SCHEMA_FILE = "schema.xml";
public static final String DEFAULT_SEARCH_FIELD = "defaultSearchField"; public static final String DEFAULT_SEARCH_FIELD = "defaultSearchField";
public static final String DESTINATION = "dest"; public static final String DESTINATION = "dest";
@ -112,7 +111,6 @@ public class IndexSchema {
public static final String SCHEMA = "schema"; public static final String SCHEMA = "schema";
public static final String SIMILARITY = "similarity"; public static final String SIMILARITY = "similarity";
public static final String SLASH = "/"; public static final String SLASH = "/";
public static final String SOLR_QUERY_PARSER = "solrQueryParser";
public static final String SOURCE = "source"; public static final String SOURCE = "source";
public static final String TYPE = "type"; public static final String TYPE = "type";
public static final String TYPES = "types"; public static final String TYPES = "types";
@ -148,9 +146,6 @@ public class IndexSchema {
protected List<SchemaAware> schemaAware = new ArrayList<>(); protected List<SchemaAware> schemaAware = new ArrayList<>();
protected String defaultSearchFieldName=null; protected String defaultSearchFieldName=null;
protected String queryParserDefaultOperator = "OR";
protected boolean isExplicitQueryParserDefaultOperator = false;
protected Map<String, List<CopyField>> copyFieldsMap = new HashMap<>(); protected Map<String, List<CopyField>> copyFieldsMap = new HashMap<>();
public Map<String,List<CopyField>> getCopyFieldsMap() { return Collections.unmodifiableMap(copyFieldsMap); } public Map<String,List<CopyField>> getCopyFieldsMap() { return Collections.unmodifiableMap(copyFieldsMap); }
@ -312,13 +307,6 @@ public class IndexSchema {
return defaultSearchFieldName; return defaultSearchFieldName;
} }
/**
* default operator ("AND" or "OR") for QueryParser
*/
public String getQueryParserDefaultOperator() {
return queryParserDefaultOperator;
}
protected SchemaField uniqueKeyField; protected SchemaField uniqueKeyField;
/** /**
@ -540,15 +528,10 @@ public class IndexSchema {
} }
// /schema/solrQueryParser/@defaultOperator // /schema/solrQueryParser/@defaultOperator
expression = stepsToPath(SCHEMA, SOLR_QUERY_PARSER, AT + DEFAULT_OPERATOR); expression = stepsToPath(SCHEMA, "solrQueryParser", AT + "defaultOperator");
node = (Node) xpath.evaluate(expression, document, XPathConstants.NODE); node = (Node) xpath.evaluate(expression, document, XPathConstants.NODE);
if (node==null) { if (node != null) {
log.debug("Default query parser operator not set in Schema"); throw new SolrException(ErrorCode.SERVER_ERROR, "Setting default operator in schema (solrQueryParser/@defaultOperator) not supported");
} else {
isExplicitQueryParserDefaultOperator = true;
queryParserDefaultOperator=node.getNodeValue().trim();
log.warn("[{}] query parser default operator is {}. WARNING: Deprecated, please use 'q.op' on request instead.",
coreName, queryParserDefaultOperator);
} }
// /schema/uniqueKey/text() // /schema/uniqueKey/text()
@ -1402,9 +1385,6 @@ public class IndexSchema {
VERSION(IndexSchema.VERSION, sp -> sp.schema.getVersion()), VERSION(IndexSchema.VERSION, sp -> sp.schema.getVersion()),
UNIQUE_KEY(IndexSchema.UNIQUE_KEY, sp -> sp.schema.uniqueKeyFieldName), UNIQUE_KEY(IndexSchema.UNIQUE_KEY, sp -> sp.schema.uniqueKeyFieldName),
DEFAULT_SEARCH_FIELD(IndexSchema.DEFAULT_SEARCH_FIELD, sp -> sp.schema.defaultSearchFieldName), DEFAULT_SEARCH_FIELD(IndexSchema.DEFAULT_SEARCH_FIELD, sp -> sp.schema.defaultSearchFieldName),
SOLR_QUERY_PARSER(IndexSchema.SOLR_QUERY_PARSER, sp -> sp.schema.isExplicitQueryParserDefaultOperator ?
singletonMap(DEFAULT_OPERATOR, sp.schema.queryParserDefaultOperator) :
null),
SIMILARITY(IndexSchema.SIMILARITY, sp -> sp.schema.isExplicitSimilarity ? SIMILARITY(IndexSchema.SIMILARITY, sp -> sp.schema.isExplicitSimilarity ?
sp.schema.similarityFactory.getNamedPropertyValues() : sp.schema.similarityFactory.getNamedPropertyValues() :
null), null),

View File

@ -1358,8 +1358,6 @@ public final class ManagedIndexSchema extends IndexSchema {
newSchema.name = name; newSchema.name = name;
newSchema.version = version; newSchema.version = version;
newSchema.defaultSearchFieldName = defaultSearchFieldName; newSchema.defaultSearchFieldName = defaultSearchFieldName;
newSchema.queryParserDefaultOperator = queryParserDefaultOperator;
newSchema.isExplicitQueryParserDefaultOperator = isExplicitQueryParserDefaultOperator;
newSchema.similarity = similarity; newSchema.similarity = similarity;
newSchema.similarityFactory = similarityFactory; newSchema.similarityFactory = similarityFactory;
newSchema.isExplicitSimilarity = isExplicitSimilarity; newSchema.isExplicitSimilarity = isExplicitSimilarity;

View File

@ -156,7 +156,7 @@ public class ComplexPhraseQParserPlugin extends QParserPlugin {
lparser.setInOrder(inOrder); lparser.setInOrder(inOrder);
QueryParser.Operator defaultOperator = QueryParsing.getQueryParserDefaultOperator(getReq().getSchema(), getParam(QueryParsing.OP)); QueryParser.Operator defaultOperator = QueryParsing.parseOP(getParam(QueryParsing.OP));
if (QueryParser.Operator.AND.equals(defaultOperator)) if (QueryParser.Operator.AND.equals(defaultOperator))
lparser.setDefaultOperator(org.apache.lucene.queryparser.classic.QueryParser.Operator.AND); lparser.setDefaultOperator(org.apache.lucene.queryparser.classic.QueryParser.Operator.AND);

View File

@ -52,14 +52,13 @@ public class DisMaxQParser extends QParser {
* Applies the appropriate default rules for the "mm" param based on the * Applies the appropriate default rules for the "mm" param based on the
* effective value of the "q.op" param * effective value of the "q.op" param
* *
* @see QueryParsing#getQueryParserDefaultOperator
* @see QueryParsing#OP * @see QueryParsing#OP
* @see DisMaxParams#MM * @see DisMaxParams#MM
*/ */
public static String parseMinShouldMatch(final IndexSchema schema, public static String parseMinShouldMatch(final IndexSchema schema,
final SolrParams params) { final SolrParams params) {
org.apache.solr.parser.QueryParser.Operator op = QueryParsing.getQueryParserDefaultOperator org.apache.solr.parser.QueryParser.Operator op = QueryParsing.parseOP(params.get(QueryParsing.OP));
(schema, params.get(QueryParsing.OP));
return params.get(DisMaxParams.MM, return params.get(DisMaxParams.MM,
op.equals(QueryParser.Operator.AND) ? "100%" : "0%"); op.equals(QueryParser.Operator.AND) ? "100%" : "0%");
} }

View File

@ -990,8 +990,7 @@ public class ExtendedDismaxQParser extends QParser {
super(parser, defaultField); super(parser, defaultField);
// Respect the q.op parameter before mm will be applied later // Respect the q.op parameter before mm will be applied later
SolrParams defaultParams = SolrParams.wrapDefaults(parser.getLocalParams(), parser.getParams()); SolrParams defaultParams = SolrParams.wrapDefaults(parser.getLocalParams(), parser.getParams());
QueryParser.Operator defaultOp = QueryParsing.getQueryParserDefaultOperator( QueryParser.Operator defaultOp = QueryParsing.parseOP(defaultParams.get(QueryParsing.OP));
parser.getReq().getSchema(), defaultParams.get(QueryParsing.OP));
setDefaultOperator(defaultOp); setDefaultOperator(defaultOp);
} }

View File

@ -44,9 +44,7 @@ public class LuceneQParser extends QParser {
} }
lparser = new SolrQueryParser(this, defaultField); lparser = new SolrQueryParser(this, defaultField);
lparser.setDefaultOperator lparser.setDefaultOperator(QueryParsing.parseOP(getParam(QueryParsing.OP)));
(QueryParsing.getQueryParserDefaultOperator(getReq().getSchema(),
getParam(QueryParsing.OP)));
lparser.setSplitOnWhitespace(StrUtils.parseBool lparser.setSplitOnWhitespace(StrUtils.parseBool
(getParam(QueryParsing.SPLIT_ON_WHITESPACE), SolrQueryParser.DEFAULT_SPLIT_ON_WHITESPACE)); (getParam(QueryParsing.SPLIT_ON_WHITESPACE), SolrQueryParser.DEFAULT_SPLIT_ON_WHITESPACE));

View File

@ -59,18 +59,15 @@ public class QueryParsing {
/** /**
* Returns the "preferred" default operator for use by Query Parsers, * Returns the default operator for use by Query Parsers, parsed from the df string
* based on the settings in the IndexSchema which may be overridden using * @param notUsed is not used, but is there for back compat with 3rd party QParsers
* an optional String override value. * @param df the df string from request
* * @deprecated this method is here purely not to break code back compat in 7.x
* @see IndexSchema#getQueryParserDefaultOperator()
* @see #OP
*/ */
public static QueryParser.Operator getQueryParserDefaultOperator(final IndexSchema sch, @Deprecated
final String override) { public static QueryParser.Operator getQueryParserDefaultOperator(final IndexSchema notUsed,
String val = override; final String df) {
if (null == val) val = sch.getQueryParserDefaultOperator(); return parseOP(df);
return "AND".equals(val) ? QueryParser.Operator.AND : QueryParser.Operator.OR;
} }
/** /**
@ -396,4 +393,12 @@ public class QueryParsing {
return out; return out;
} }
/**
* Parses default operator string into Operator object
* @param operator the string from request
* @return Operator.AND if string equals "AND", else return Operator.OR (default)
*/
public static QueryParser.Operator parseOP(String operator) {
return "and".equalsIgnoreCase(operator) ? QueryParser.Operator.AND : QueryParser.Operator.OR;
}
} }

View File

@ -154,7 +154,7 @@ public class SimpleQParserPlugin extends QParserPlugin {
parser = new SolrSimpleQueryParser(req.getSchema().getQueryAnalyzer(), queryFields, enabledOps, this, schema); parser = new SolrSimpleQueryParser(req.getSchema().getQueryAnalyzer(), queryFields, enabledOps, this, schema);
// Set the default operator to be either 'AND' or 'OR' for the query. // Set the default operator to be either 'AND' or 'OR' for the query.
QueryParser.Operator defaultOp = QueryParsing.getQueryParserDefaultOperator(req.getSchema(), defaultParams.get(QueryParsing.OP)); QueryParser.Operator defaultOp = QueryParsing.parseOP(defaultParams.get(QueryParsing.OP));
if (defaultOp == QueryParser.Operator.AND) { if (defaultOp == QueryParser.Operator.AND) {
parser.setDefaultOperator(BooleanClause.Occur.MUST); parser.setDefaultOperator(BooleanClause.Occur.MUST);

View File

@ -11,8 +11,7 @@
"/schema/version", "/schema/version",
"/schema/similarity", "/schema/similarity",
"/schema/solrqueryparser", "/schema/solrqueryparser",
"/schema/zkversion", "/schema/zkversion"
"/schema/solrqueryparser/defaultoperator"
] ]
} }
} }

View File

@ -0,0 +1,26 @@
<?xml version="1.0" ?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<schema name="bad-schema-default-operator" version="1.6">
<fieldType name="string" class="solr.StrField"/>
<field name="id" type="string" indexed="true" stored="true" multiValued="false" required="false"/>
<uniqueKey>id</uniqueKey>
<!-- BEGIN BAD STUFF: not allowed anymore -->
<solrQueryParser defaultOperator="OR"/>
<!-- END BAD STUFF -->
</schema>

View File

@ -1,29 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.rest.schema;
import org.apache.solr.rest.SolrRestletTestBase;
import org.junit.Test;
public class TestSolrQueryParserDefaultOperatorResource extends SolrRestletTestBase {
@Test
public void testGetDefaultOperator() throws Exception {
assertQ("/schema/solrqueryparser/defaultoperator?indent=on&wt=xml",
"count(/response/str[@name='defaultOperator']) = 1",
"/response/str[@name='defaultOperator'][.='OR']");
}
}

View File

@ -1,30 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.rest.schema;
import org.apache.solr.rest.SolrRestletTestBase;
import org.junit.Test;
public class TestSolrQueryParserResource extends SolrRestletTestBase {
@Test
public void testGetSolrQueryParser() throws Exception {
assertQ("/schema/solrqueryparser?indent=on&wt=xml",
"count(/response/lst[@name='solrQueryParser']) = 1",
"count(/response/lst[@name='solrQueryParser']/str[@name='defaultOperator']) = 1",
"/response/lst[@name='solrQueryParser']/str[@name='defaultOperator'][.='OR']");
}
}

View File

@ -127,5 +127,9 @@ public class BadIndexSchemaTest extends AbstractBadConfigTestBase {
doTest("bad-schema-sim-default-does-not-exist.xml", doTest("bad-schema-sim-default-does-not-exist.xml",
"ft-does-not-exist"); "ft-does-not-exist");
} }
public void testDefaultOperatorBanned() throws Exception {
doTest("bad-schema-default-operator.xml",
"default operator in schema (solrQueryParser/@defaultOperator) not supported");
}
} }