浏览代码

[Rest Api Compatibility] Typed query (#75453)

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
Przemyslaw Gomulka 4 年之前
父节点
当前提交
f3392829d6

+ 4 - 2
rest-api-spec/build.gradle

@@ -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 {
@@ -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(',')
 

+ 52 - 0
rest-api-spec/src/yamlRestCompatTest/resources/rest-api-spec/test/v7compat/search/10_type_query.yml

@@ -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\\].*"
+

+ 97 - 0
server/src/main/java/org/elasticsearch/index/query/TypeQueryV7Builder.java

@@ -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;
+    }
+}

+ 8 - 1
server/src/main/java/org/elasticsearch/search/SearchModule.java

@@ -11,7 +11,6 @@ package org.elasticsearch.search;
 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;
@@ -21,8 +20,10 @@ import org.elasticsearch.common.io.stream.Writeable;
 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;
@@ -67,6 +68,7 @@ import org.elasticsearch.index.query.SpanWithinQueryBuilder;
 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;
@@ -839,6 +841,10 @@ public class SearchModule {
         }
 
         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() {
@@ -893,4 +899,5 @@ public class SearchModule {
     public FetchPhase getFetchPhase() {
         return new FetchPhase(fetchSubPhases);
     }
+
 }

+ 9 - 3
server/src/test/java/org/elasticsearch/search/SearchModuleTests.java

@@ -25,6 +25,7 @@ import org.elasticsearch.index.query.QueryBuilder;
 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;
@@ -241,11 +242,14 @@ public class SearchModuleTests extends ESTestCase {
         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()
@@ -389,6 +393,7 @@ public class SearchModuleTests extends ESTestCase {
 
     //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.
@@ -669,14 +674,15 @@ public class SearchModuleTests extends ESTestCase {
                 .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));
     }