SOLR-10585: Remove defaultSearchField completely in 7.0

This commit is contained in:
Jan Høydahl 2017-05-19 15:25:40 +02:00
parent 467af790cb
commit 4a57fb4d88
28 changed files with 77 additions and 110 deletions

View File

@ -73,6 +73,9 @@ Upgrading from Solr 6.x
* 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.
* Setting <defaultSearchField> in schema is no longer allowed and will cause an exception.
Please use "df" parameter on the request instead. For more details, see SOLR-10585.
New Features
----------------------
* SOLR-9857, SOLR-9858: Collect aggregated metrics from nodes and shard leaders in overseer. (ab)
@ -159,6 +162,9 @@ Other Changes
* 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)
* SOLR-10585: We'll now always throw an exception if defaultSearchField is found in schema. This config has
been deprecated since 3.6, and enforced for new configs since 6.6 (janhoy, David Smiley)
* SOLR-10414: RecoveryStrategy is now a Runnable instead of a Thread. (Tomás Fernández Löbbe)
* SOLR-10042: Delete old deprecated Admin UI, leaving the AngularJS UI the only one supported (janhoy)

View File

@ -116,7 +116,7 @@ public class FieldAnalysisRequestHandler extends AnalysisRequestHandlerBase {
* @return AnalysisRequest containing all the information about what needs to be analyzed, and using what
* fields/types
*/
FieldAnalysisRequest resolveAnalysisRequest(SolrQueryRequest req) {
FieldAnalysisRequest resolveAnalysisRequest(SolrQueryRequest req) throws SolrException {
SolrParams solrParams = req.getParams();
FieldAnalysisRequest analysisRequest = new FieldAnalysisRequest();
@ -129,8 +129,13 @@ public class FieldAnalysisRequestHandler extends AnalysisRequestHandlerBase {
analysisRequest.setFieldNames(Arrays.asList(solrParams.get(AnalysisParams.FIELD_NAME).split(",")));
useDefaultSearchField = false;
}
if (useDefaultSearchField) {
analysisRequest.addFieldName(req.getSchema().getDefaultSearchFieldName());
if (useDefaultSearchField) {
if (solrParams.get(CommonParams.DF) != null) {
analysisRequest.addFieldName(solrParams.get(CommonParams.DF));
} else {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
"Field analysis request must contain one of analysis.fieldtype, analysis.fieldname or df.");
}
}
analysisRequest.setQuery(solrParams.get(AnalysisParams.QUERY, solrParams.get(CommonParams.Q)));

View File

@ -137,15 +137,6 @@ public class SchemaHandler extends RequestHandlerBase implements SolrCoreAware,
rsp.add(IndexSchema.NAME, schemaName);
break;
}
case "/schema/defaultsearchfield": {
final String defaultSearchFieldName = req.getSchema().getDefaultSearchFieldName();
if (null == defaultSearchFieldName) {
final String message = "undefined " + IndexSchema.DEFAULT_SEARCH_FIELD;
throw new SolrException(SolrException.ErrorCode.NOT_FOUND, message);
}
rsp.add(IndexSchema.DEFAULT_SEARCH_FIELD, defaultSearchFieldName);
break;
}
case "/schema/zkversion": {
int refreshIfBelowVersion = -1;
Object refreshParam = req.getParams().get("refreshIfBelowVersion");

View File

@ -472,7 +472,6 @@ public class LukeRequestHandler extends RequestHandlerBase
finfo.add("uniqueKeyField",
null == uniqueField ? null : uniqueField.getName());
finfo.add("defaultSearchField", schema.getDefaultSearchFieldName());
finfo.add("similarity", getSimilarityInfo(schema.getSimilarity()));
finfo.add("types", types);
return finfo;

View File

@ -26,7 +26,6 @@ import java.util.stream.Stream;
import com.google.common.base.Objects;
import org.apache.lucene.search.Query;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.HighlightParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
@ -154,12 +153,8 @@ public class HighlightComponent extends SearchComponent implements PluginInfoIni
SolrHighlighter highlighter = getHighlighter(params);
String[] defaultHighlightFields; //TODO: get from builder by default?
if (rb.getQparser() != null) {
defaultHighlightFields = rb.getQparser().getDefaultHighlightFields();
} else {
defaultHighlightFields = params.getParams(CommonParams.DF);
}
//TODO: get from builder by default?
String[] defaultHighlightFields = rb.getQparser() != null ? rb.getQparser().getDefaultHighlightFields() : null;
Query highlightQuery = rb.getHighlightQuery();
if(highlightQuery==null) {

View File

@ -16,6 +16,7 @@
*/
package org.apache.solr.highlight;
import org.apache.lucene.search.Query;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.HighlightParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
@ -56,9 +57,9 @@ public abstract class SolrHighlighter
// if no fields specified in the request, or the handler, fall back to programmatic default, or default search field.
if(emptyArray(fields)) {
// use default search field if highlight fieldlist not specified.
// use default search field from request if highlight fieldlist not specified.
if (emptyArray(defaultFields)) {
String defaultSearchField = request.getSchema().getDefaultSearchFieldName();
String defaultSearchField = request.getParams().get(CommonParams.DF);
fields = null == defaultSearchField ? new String[]{} : new String[]{defaultSearchField};
} else {
fields = defaultFields;

View File

@ -98,11 +98,6 @@ public class SchemaXmlWriter extends TextResponseWriter {
closeStartTag(false);
writer.write(val.toString());
endTag(IndexSchema.UNIQUE_KEY, false);
} else if (schemaPropName.equals(IndexSchema.DEFAULT_SEARCH_FIELD)) {
openStartTag(IndexSchema.DEFAULT_SEARCH_FIELD);
closeStartTag(false);
writer.write(val.toString());
endTag(IndexSchema.DEFAULT_SEARCH_FIELD, false);
} else if (schemaPropName.equals(IndexSchema.SIMILARITY)) {
writeSimilarity((SimpleOrderedMap<Object>) val);
} else if (schemaPropName.equals(IndexSchema.FIELD_TYPES)) {

View File

@ -95,7 +95,6 @@ public class IndexSchema {
public static final String COPY_FIELD = "copyField";
public static final String COPY_FIELDS = COPY_FIELD + "s";
public static final String DEFAULT_SCHEMA_FILE = "schema.xml";
public static final String DEFAULT_SEARCH_FIELD = "defaultSearchField";
public static final String DESTINATION = "dest";
public static final String DYNAMIC_FIELD = "dynamicField";
public static final String DYNAMIC_FIELDS = DYNAMIC_FIELD + "s";
@ -145,8 +144,6 @@ public class IndexSchema {
protected List<SchemaAware> schemaAware = new ArrayList<>();
protected String defaultSearchFieldName=null;
protected Map<String, List<CopyField>> copyFieldsMap = new HashMap<>();
public Map<String,List<CopyField>> getCopyFieldsMap() { return Collections.unmodifiableMap(copyFieldsMap); }
@ -298,15 +295,6 @@ public class IndexSchema {
public Analyzer getQueryAnalyzer() { return queryAnalyzer; }
/**
* Name of the default search field specified in the schema file.
* <br><b>Note:</b>Avoid calling this, try to use this method so that the 'df' param is consulted as an override:
* {@link org.apache.solr.search.QueryParsing#getDefaultField(IndexSchema, String)}
*/
public String getDefaultSearchFieldName() {
return defaultSearchFieldName;
}
protected SchemaField uniqueKeyField;
/**
@ -509,22 +497,10 @@ public class IndexSchema {
}
// /schema/defaultSearchField/text()
expression = stepsToPath(SCHEMA, DEFAULT_SEARCH_FIELD, TEXT_FUNCTION);
expression = stepsToPath(SCHEMA, "defaultSearchField", TEXT_FUNCTION);
node = (Node) xpath.evaluate(expression, document, XPathConstants.NODE);
if (node==null) {
log.debug("no default search field specified in schema.");
} else {
defaultSearchFieldName=node.getNodeValue().trim();
// throw exception if specified, but not found or not indexed
if (defaultSearchFieldName!=null) {
SchemaField defaultSearchField = getFields().get(defaultSearchFieldName);
if ((defaultSearchField == null) || !defaultSearchField.indexed()) {
String msg = "default search field '" + defaultSearchFieldName + "' not defined or not indexed" ;
throw new SolrException(ErrorCode.SERVER_ERROR, msg);
}
}
log.warn("[{}] default search field in schema is {}. WARNING: Deprecated, please use 'df' on request instead.",
coreName, defaultSearchFieldName);
if (node != null) {
throw new SolrException(ErrorCode.SERVER_ERROR, "Setting defaultSearchField in schema not supported since Solr 7");
}
// /schema/solrQueryParser/@defaultOperator
@ -1384,7 +1360,6 @@ public class IndexSchema {
NAME(IndexSchema.NAME, sp -> sp.schema.getSchemaName()),
VERSION(IndexSchema.VERSION, sp -> sp.schema.getVersion()),
UNIQUE_KEY(IndexSchema.UNIQUE_KEY, sp -> sp.schema.uniqueKeyFieldName),
DEFAULT_SEARCH_FIELD(IndexSchema.DEFAULT_SEARCH_FIELD, sp -> sp.schema.defaultSearchFieldName),
SIMILARITY(IndexSchema.SIMILARITY, sp -> sp.schema.isExplicitSimilarity ?
sp.schema.similarityFactory.getNamedPropertyValues() :
null),

View File

@ -1357,7 +1357,6 @@ public final class ManagedIndexSchema extends IndexSchema {
newSchema.name = name;
newSchema.version = version;
newSchema.defaultSearchFieldName = defaultSearchFieldName;
newSchema.similarity = similarity;
newSchema.similarityFactory = similarityFactory;
newSchema.isExplicitSimilarity = isExplicitSimilarity;

View File

@ -110,9 +110,6 @@ public class ComplexPhraseQParserPlugin extends QParserPlugin {
String qstr = getString();
String defaultField = getParam(CommonParams.DF);
if (defaultField == null) {
defaultField = getReq().getSchema().getDefaultSearchFieldName();
}
SolrQueryParserDelegate reverseAwareParser = new SolrQueryParserDelegate(this, defaultField);

View File

@ -65,15 +65,14 @@ public class DisMaxQParser extends QParser {
/**
* Uses {@link SolrPluginUtils#parseFieldBoosts(String)} with the 'qf' parameter. Falls back to the 'df' parameter
* or {@link org.apache.solr.schema.IndexSchema#getDefaultSearchFieldName()}.
*/
public static Map<String, Float> parseQueryFields(final IndexSchema indexSchema, final SolrParams solrParams)
throws SyntaxError {
Map<String, Float> queryFields = SolrPluginUtils.parseFieldBoosts(solrParams.getParams(DisMaxParams.QF));
if (queryFields.isEmpty()) {
String df = QueryParsing.getDefaultField(indexSchema, solrParams.get(CommonParams.DF));
String df = solrParams.get(CommonParams.DF);
if (df == null) {
throw new SyntaxError("Neither "+DisMaxParams.QF+", "+CommonParams.DF +", nor the default search field are present.");
throw new SyntaxError("Neither "+DisMaxParams.QF+" nor "+CommonParams.DF +" are present.");
}
queryFields.put(df, 1.0f);
}

View File

@ -39,9 +39,6 @@ public class LuceneQParser extends QParser {
if (qstr == null || qstr.length()==0) return null;
String defaultField = getParam(CommonParams.DF);
if (defaultField==null) {
defaultField = getReq().getSchema().getDefaultSearchFieldName();
}
lparser = new SolrQueryParser(this, defaultField);
lparser.setDefaultOperator(QueryParsing.parseOP(getParam(QueryParsing.OP)));

View File

@ -71,13 +71,16 @@ public class QueryParsing {
}
/**
* Returns the effective default field based on the 'df' param or
* hardcoded schema default. May be null if either exists specified.
* Returns the effective default field based on the 'df' param.
* TODO: This is kept for 3rd party QParser compat in 7.x. Remove this method in Solr 8.0
* @param ignored Not in use
* @param df the default field, which will be returned as-is
* @see org.apache.solr.common.params.CommonParams#DF
* @see org.apache.solr.schema.IndexSchema#getDefaultSearchFieldName
* @deprecated IndexScema does not contain defaultField anymore, you must rely on df alone
*/
public static String getDefaultField(final IndexSchema s, final String df) {
return df != null ? df : s.getDefaultSearchFieldName();
@Deprecated
public static String getDefaultField(final IndexSchema ignored, final String df) {
return df;
}
/**

View File

@ -109,12 +109,12 @@ public class SimpleQParserPlugin extends QParserPlugin {
if (queryFields.isEmpty()) {
// It qf is not specified setup up the queryFields map to use the defaultField.
String defaultField = QueryParsing.getDefaultField(req.getSchema(), defaultParams.get(CommonParams.DF));
String defaultField = defaultParams.get(CommonParams.DF);
if (defaultField == null) {
// A query cannot be run without having a field or set of fields to run against.
throw new IllegalStateException("Neither " + SimpleParams.QF + ", " + CommonParams.DF
+ ", nor the default search field are present.");
throw new IllegalStateException("Neither " + SimpleParams.QF + " nor " + CommonParams.DF
+ " are present.");
}
queryFields.put(defaultField, 1.0F);

View File

@ -95,7 +95,7 @@ public class SurroundQParserPlugin extends QParserPlugin {
// processing based on example in LIA Ch 9
BasicQueryFactory bqFactory = new BasicQueryFactory(this.maxBasicQueries);
String defaultField = QueryParsing.getDefaultField(getReq().getSchema(),getParam(CommonParams.DF));
String defaultField = getParam(CommonParams.DF);
Query lquery = sq.makeLuceneQueryField(defaultField, bqFactory);
return lquery;
}

View File

@ -53,7 +53,7 @@ public class XmlQParserPlugin extends QParserPlugin {
return null;
}
final IndexSchema schema = req.getSchema();
final String defaultField = QueryParsing.getDefaultField(schema, getParam(CommonParams.DF));
final String defaultField = getParam(CommonParams.DF);
final Analyzer analyzer = schema.getQueryAnalyzer();
final SolrCoreParser solrParser = new SolrCoreParser(defaultField, analyzer, req);

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-defaultsearchfield" 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 -->
<defaultSearchField>id</defaultSearchField>
<!-- END BAD STUFF -->
</schema>

View File

@ -88,7 +88,6 @@ public class MinimalSchemaTest extends SolrTestCaseJ4 {
"show","schema")
,"//int[@name='numDocs'][.='2']"
,"//null[@name='uniqueKeyField']"
,"//null[@name='defaultSearchField']"
);
}

View File

@ -479,6 +479,14 @@ public class FieldAnalysisRequestHandlerTest extends AnalysisRequestHandlerTestB
assertEquals(901, tokenInfoList.get(0).get("org.apache.lucene.analysis.tokenattributes.FlagsAttribute#flags"));
}
@Test(expected = Exception.class)
public void testNoDefaultField() throws Exception {
ModifiableSolrParams params = new ModifiableSolrParams();
params.add(CommonParams.Q, "fox brown");
SolrQueryRequest req = new LocalSolrQueryRequest(h.getCore(), params);
handler.resolveAnalysisRequest(req);
}
/** A custom impl of a standard attribute impl; test this instance is used. */
public class CustomFlagsAttributeImpl extends FlagsAttributeImpl {
@Override

View File

@ -132,4 +132,8 @@ public class BadIndexSchemaTest extends AbstractBadConfigTestBase {
doTest("bad-schema-default-operator.xml",
"default operator in schema (solrQueryParser/@defaultOperator) not supported");
}
public void testSchemaWithDefaultSearchField() throws Exception {
doTest("bad-schema-defaultsearchfield.xml", "Setting defaultSearchField in schema not supported since Solr 7");
}
}

View File

@ -35,7 +35,6 @@ import org.apache.lucene.search.TermQuery;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.search.QParser;
import org.apache.solr.search.QueryParsing;
import org.apache.solr.util.SolrPluginUtils.DisjunctionMaxQueryParser;
import org.junit.BeforeClass;
import org.junit.Test;
@ -131,7 +130,7 @@ public class SolrPluginUtilsTest extends SolrTestCaseJ4 {
QParser qparser = QParser.getParser("hi", "dismax", req);
DisjunctionMaxQueryParser qp =
new SolrPluginUtils.DisjunctionMaxQueryParser(qparser, QueryParsing.getDefaultField(req.getSchema(), req.getParams().get("df")));
new SolrPluginUtils.DisjunctionMaxQueryParser(qparser, req.getParams().get("df"));
qp.addAlias("hoss", 0.01f, SolrPluginUtils.parseFieldBoosts
("title^2.0 title_stemmed name^1.2 subject^0.5"));

View File

@ -25,7 +25,7 @@
<field name="title" type="text_simple" indexed="true" stored="true" multiValued="true"/>
<field name="format" type="string" indexed="true" stored="true"/>
<!-- field "text" is searchable (it is the default search field) but it is not stored to save space -->
<!-- field "text" is searchable but it is not stored to save space -->
<field name="text" type="text_simple" indexed="true" stored="false" multiValued="true"/>

View File

@ -21,13 +21,6 @@ Schema defaults and `copyFields` cannot be used to populate the `uniqueKey` fiel
Further, the operation will fail if the `uniqueKey` field is used, but is multivalued (or inherits the multivalue-ness from the `fieldtype`). However, `uniqueKey` will continue to work, as long as the field is properly used.
[[OtherSchemaElements-DefaultSearchField]]
== Default Search Field
Although it has been deprecated for quite some time, Solr still has support for Schema based configuration of a `<defaultSearchField/>` (which is superseded by the <<the-standard-query-parser.adoc#the-standard-query-parser,`df parameter`>>).
If you have this option specified in your Schema, you are strongly encouraged to replace it with request parameters (or <<request-parameters-api.adoc#request-parameters-api,request parameter defaults>>) as support for it will be removed from future Solr release.
[[OtherSchemaElements-Similarity]]
== Similarity

View File

@ -22,8 +22,6 @@ These are supplemented by `copyFields`.
The `uniqueKey` must always be defined.
In older Solr versions you would find `defaultSearchField` and `solrQueryParser` tags as well, but although these still work they are deprecated and discouraged, see <<other-schema-elements.adoc#other-schema-elements,Other Schema Elements>>.
.Types and fields are optional tags
[NOTE]
====

View File

@ -29,8 +29,6 @@ public class SchemaRepresentation {
private String uniqueKey;
private String defaultSearchField;
private Map<String, Object> similarity;
private List<Map<String, Object>> fields;
@ -66,14 +64,6 @@ public class SchemaRepresentation {
this.uniqueKey = uniqueKey;
}
public String getDefaultSearchField() {
return defaultSearchField;
}
public void setDefaultSearchField(String defaultSearchField) {
this.defaultSearchField = defaultSearchField;
}
public Map<String, Object> getSimilarity() {
return similarity;
}

View File

@ -137,7 +137,6 @@ public class SchemaResponse extends SolrResponseBase {
schemaRepresentation.setName(getSchemaName(schemaObj));
schemaRepresentation.setVersion(getSchemaVersion(schemaObj));
schemaRepresentation.setUniqueKey(getSchemaUniqueKey(schemaObj));
schemaRepresentation.setDefaultSearchField(getDefaultSearchField(schemaObj));
schemaRepresentation.setSimilarity(getSimilarity(schemaObj));
schemaRepresentation.setFields(getFields(schemaObj));
schemaRepresentation.setDynamicFields(getDynamicFields(schemaObj));
@ -158,10 +157,6 @@ public class SchemaResponse extends SolrResponseBase {
return (String) schemaNamedList.get("uniqueKey");
}
private static String getDefaultSearchField(Map schemaNamedList) {
return (String) schemaNamedList.get("defaultSearchField");
}
private static Map<String, Object> getSimilarity(Map schemaNamedList) {
NamedList<Object> similarityNamedList = (NamedList<Object>) schemaNamedList.get("similarity");
Map<String, Object> similarity = null;

View File

@ -68,13 +68,11 @@ solrAdminApp.controller('SchemaController',
}
$scope.leftbar = leftbar;
$scope.core = $routeParams.core;
$scope.defaultSearchField = data.default_search_field;
$scope.uniqueKeyField = data.unique_key_field;
$scope.similarity = data.similarity;
if ($scope.similarity && $scope.similarity.className) {
$scope.similarity.className = shortenPackages($scope.similarity.className);
}
$scope.isDefaultSearchField = ($scope.selectedType == "Field" && $scope.name == $scope.defaultSearchField);
$scope.isUniqueKeyField = ($scope.selectedType == "Field" && $scope.name == $scope.uniqueKeyField);
$scope.display = getFieldProperties(data, $routeParams.core, $scope.is, $scope.name);
@ -336,7 +334,6 @@ var filterFields = function(type, data, name) {
var mergeIndexAndSchemaData = function(index, schema) {
var data = {
default_search_field: null,
unique_key_field: null,
similarity: null,
key: {},
@ -357,7 +354,6 @@ var mergeIndexAndSchemaData = function(index, schema) {
data.key = index.info.key;
data.default_search_field = schema.defaultSearchField;
data.unique_key_field = schema.uniqueKeyField;
data.similarity = schema.similarity;

View File

@ -435,9 +435,6 @@ limitations under the License.
<dt class="unique-key-field" ng-class="{active: isUniqueKeyField}" ng-show="uniqueKeyField">Unique Key Field</dt>
<dd class="unique-key-field" ng-class="{active: isUniqueKeyField}"><a ng-href="#/{{core}}/schema?field={{uniqueKeyField}}">{{uniqueKeyField}}</a></dd>
<dt class="default-search-field" ng-class="{active: isDefaultSearchField}" ng-show="defaultSearchField">Default Search Field</dt>
<dd class="default-search-field" ng-class="{active: isDefaultSearchField}"><a ng-href="#/{{core}}/schema?field={{defaultSearchField}}">{{defaultSearchField}}</a></dd>
<dt class="similarity" ng-class="{active: similarity.className}">Global Similarity:</dt>
<dd class="similarity" ng-class="{active: similarity.className}" data-tip="{{ similarity.className }}">{{ similarity.details }}</dd>