Skip to content

Commit

Permalink
[Rest Api Compatibility] Typed query (#75453)
Browse files Browse the repository at this point in the history
Type query support was removed in #47207. This query will throw an exception in v7 rest api compatibility indicating that the support was removed + deprecation warnings.
In v8 it will not be available and error about type query being not found will be returned.

relates main meta issue #51816
relates types removal meta #54160
  • Loading branch information
pgomulka committed Aug 3, 2021
1 parent d671e3f commit f339282
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 6 deletions.
6 changes: 4 additions & 2 deletions rest-api-spec/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ def v7compatibilityNotSupportedTests = {

'field_caps/30_filter/Field caps with index filter', //behaviour change after #63692 4digits dates are parsed as epoch and in quotes as year

'indices.forcemerge/10_basic/Check deprecation warning when incompatible only_expunge_deletes and max_num_segments values are both set', //#44761 bug fix
'indices.forcemerge/10_basic/Check deprecation warning when incompatible only_expunge_deletes and max_num_segments values are both set', //#44761 bug fix,

'search/340_type_query/type query' //#47207 type query throws exception in compatible mode

]
}
tasks.named("yamlRestCompatTest").configure {
Expand All @@ -91,7 +94,6 @@ tasks.named("yamlRestCompatTest").configure {
systemProperty 'tests.rest.blacklist', ([
'search.aggregation/200_top_hits_metric/top_hits aggregation with sequence numbers',
'search/310_match_bool_prefix/multi_match multiple fields with cutoff_frequency throws exception', //cutoff_frequency
'search/340_type_query/type query', // type_query - probably should behave like match_all
] + v7compatibilityNotSupportedTests())
.join(',')

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
setup:
- skip:
features:
- "headers"
- "allowed_warnings_regex"
---
type query throws exception when used:
- do:
index:
index: "test1"
id: 1
type: "cat"
refresh: true
body:
foo: "bar"
headers:
Content-Type: "application/vnd.elasticsearch+json;compatible-with=7"
Accept: "application/vnd.elasticsearch+json;compatible-with=7"
allowed_warnings_regex:
- "\\[types removal\\].*"

- do:
catch: /\[types removal\] Type queries are deprecated, prefer to filter on a field instead./
search:
rest_total_hits_as_int: true
index: "test1"
body:
query:
type:
value: "cat"
headers:
Content-Type: "application/vnd.elasticsearch+json;compatible-with=7"
Accept: "application/vnd.elasticsearch+json;compatible-with=7"
allowed_warnings_regex:
- "\\[types removal\\].*"

- do:
catch: /\[types removal\] Type queries are deprecated, prefer to filter on a field instead./
search:
rest_total_hits_as_int: true
index: "test1"
body:
query:
type:
value: "_doc"
headers:
Content-Type: "application/vnd.elasticsearch+json;compatible-with=7"
Accept: "application/vnd.elasticsearch+json;compatible-with=7"
allowed_warnings_regex:
- "\\[types removal\\].*"

Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

package org.elasticsearch.index.query;

import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.ParseField;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.core.RestApiVersion;
import org.elasticsearch.index.mapper.MapperService;

import java.io.IOException;

public class TypeQueryV7Builder extends AbstractQueryBuilder<TypeQueryV7Builder> {
private static final DeprecationLogger deprecationLogger = DeprecationLogger.getLogger(TypeQueryV7Builder.class);
public static final String TYPES_DEPRECATION_MESSAGE = "[types removal] Type queries are deprecated, " +
"prefer to filter on a field instead.";

private static final String NAME = "type";
public static final ParseField NAME_V7 = new ParseField(NAME).forRestApiVersion(RestApiVersion.equalTo(RestApiVersion.V_7));
private static final ParseField VALUE_FIELD = new ParseField("value");
private static final ObjectParser<TypeQueryV7Builder, Void> PARSER = new ObjectParser<>(NAME, TypeQueryV7Builder::new);

static {
PARSER.declareString(QueryBuilder::queryName,
AbstractQueryBuilder.NAME_FIELD.forRestApiVersion(RestApiVersion.equalTo(RestApiVersion.V_7)));
PARSER.declareFloat(QueryBuilder::boost,
AbstractQueryBuilder.BOOST_FIELD.forRestApiVersion(RestApiVersion.equalTo(RestApiVersion.V_7)));
PARSER.declareString(TypeQueryV7Builder::setValue,
VALUE_FIELD.forRestApiVersion(RestApiVersion.equalTo(RestApiVersion.V_7)));
}

private String value;

public TypeQueryV7Builder() {
}

/**
* Read from a stream.
*/
public TypeQueryV7Builder(StreamInput in) throws IOException {
super(in);
}

@Override
protected void doWriteTo(StreamOutput out) throws IOException {
}

@Override
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(NAME);
builder.field(VALUE_FIELD.getPreferredName(), MapperService.SINGLE_MAPPING_NAME);
printBoostAndQueryName(builder);
builder.endObject();
}

@Override
protected Query doToQuery(SearchExecutionContext context) throws IOException {
return new MatchNoDocsQuery();
}

@Override
protected boolean doEquals(TypeQueryV7Builder other) {
return true;
}

@Override
protected int doHashCode() {
return 0;
}

public static TypeQueryV7Builder fromXContent(XContentParser parser) throws IOException {
deprecationLogger.compatibleApiWarning("type_query", TYPES_DEPRECATION_MESSAGE);
throw new ParsingException(parser.getTokenLocation(), TYPES_DEPRECATION_MESSAGE);
}

@Override
public String getWriteableName() {
return NAME;
}

public void setValue(String value){
this.value = value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import org.apache.lucene.search.BooleanQuery;
import org.elasticsearch.common.CheckedBiConsumer;
import org.elasticsearch.common.NamedRegistry;
import org.elasticsearch.common.xcontent.ParseField;
import org.elasticsearch.common.geo.GeoShapeType;
import org.elasticsearch.common.geo.ShapesAvailability;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
Expand All @@ -21,8 +20,10 @@
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.ParseField;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.core.Nullable;
import org.elasticsearch.core.RestApiVersion;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.BoostingQueryBuilder;
import org.elasticsearch.index.query.CombinedFieldsQueryBuilder;
Expand Down Expand Up @@ -67,6 +68,7 @@
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.index.query.TermsQueryBuilder;
import org.elasticsearch.index.query.TermsSetQueryBuilder;
import org.elasticsearch.index.query.TypeQueryV7Builder;
import org.elasticsearch.index.query.WildcardQueryBuilder;
import org.elasticsearch.index.query.WrapperQueryBuilder;
import org.elasticsearch.index.query.functionscore.ExponentialDecayFunctionBuilder;
Expand Down Expand Up @@ -839,6 +841,10 @@ private void registerQueryParsers(List<SearchPlugin> plugins) {
}

registerFromPlugin(plugins, SearchPlugin::getQueries, this::registerQuery);

if (RestApiVersion.minimumSupported() == RestApiVersion.V_7) {
registerQuery(new QuerySpec<>(TypeQueryV7Builder.NAME_V7, TypeQueryV7Builder::new, TypeQueryV7Builder::fromXContent));
}
}

private void registerIntervalsSourceProviders() {
Expand Down Expand Up @@ -893,4 +899,5 @@ private void registerBoolQuery(ParseField name, Writeable.Reader<QueryBuilder> r
public FetchPhase getFetchPhase() {
return new FetchPhase(fetchSubPhases);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.elasticsearch.index.query.QueryRewriteContext;
import org.elasticsearch.index.query.SearchExecutionContext;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.index.query.TypeQueryV7Builder;
import org.elasticsearch.index.query.functionscore.GaussDecayFunctionBuilder;
import org.elasticsearch.plugins.SearchPlugin;
import org.elasticsearch.search.aggregations.AggregationBuilder;
Expand Down Expand Up @@ -241,11 +242,14 @@ public void testRegisteredQueries() {
List<String> allSupportedQueries = new ArrayList<>();
Collections.addAll(allSupportedQueries, NON_DEPRECATED_QUERIES);
Collections.addAll(allSupportedQueries, DEPRECATED_QUERIES);
Collections.addAll(allSupportedQueries, REST_COMPATIBLE_QUERIES);

SearchModule module = new SearchModule(Settings.EMPTY, emptyList());

Set<String> registeredNonDeprecated = module.getNamedXContents().stream()
.filter(e -> e.categoryClass.equals(QueryBuilder.class))
.filter(e -> e.name.getAllReplacedWith() == null)
.filter(e -> RestApiVersion.current().matches(e.restApiCompatibility))
.map(e -> e.name.getPreferredName())
.collect(toSet());
Set<String> registeredAll = module.getNamedXContents().stream()
Expand Down Expand Up @@ -389,6 +393,7 @@ public CheckedBiConsumer<ShardSearchRequest, StreamOutput, IOException> getReque

//add here deprecated queries to make sure we log a deprecation warnings when they are used
private static final String[] DEPRECATED_QUERIES = new String[] {"field_masking_span", "geo_polygon"};
private static final String[] REST_COMPATIBLE_QUERIES = new String[] {TypeQueryV7Builder.NAME_V7.getPreferredName()};

/**
* Dummy test {@link AggregationBuilder} used to test registering aggregation builders.
Expand Down Expand Up @@ -669,14 +674,15 @@ public List<SearchPlugin.QuerySpec<?>> getQueries() {
.filter(e -> RestApiVersion.minimumSupported().matches(e.restApiCompatibility))
.filter(e -> RestApiVersion.current().matches(e.restApiCompatibility))
.collect(toSet()),
hasSize(searchModule.getNamedXContents().size() - 1));
hasSize(searchModule.getNamedXContents().size()- REST_COMPATIBLE_QUERIES.length - 1 ));


final List<NamedXContentRegistry.Entry> compatEntry = searchModule.getNamedXContents().stream()
.filter(e -> e.categoryClass.equals(QueryBuilder.class) &&
e.name.match(CompatQueryBuilder.NAME_OLD.getPreferredName(), LoggingDeprecationHandler.INSTANCE))
RestApiVersion.minimumSupported().matches(e.name.getForRestApiVersion()) // v7 compatbile
&& RestApiVersion.current().matches(e.name.getForRestApiVersion()) == false) // but not v8 compatible
.collect(toList());
assertThat(compatEntry, hasSize(1));
assertThat(compatEntry, hasSize(REST_COMPATIBLE_QUERIES.length + 1));//+1 because of registered in the test
assertTrue(RestApiVersion.minimumSupported().matches(compatEntry.get(0).restApiCompatibility));
assertFalse(RestApiVersion.current().matches(compatEntry.get(0).restApiCompatibility));
}
Expand Down

0 comments on commit f339282

Please sign in to comment.