Browse Source

HLRC: Adding ml get filters api (#35502)

* HLRC: Adding ml get filters api

* refactoring setId name
Benjamin Trent 7 years ago
parent
commit
b9eb5f7b63

+ 20 - 0
client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java

@@ -39,6 +39,7 @@ import org.elasticsearch.client.ml.GetCalendarsRequest;
 import org.elasticsearch.client.ml.GetCategoriesRequest;
 import org.elasticsearch.client.ml.GetDatafeedRequest;
 import org.elasticsearch.client.ml.GetDatafeedStatsRequest;
+import org.elasticsearch.client.ml.GetFiltersRequest;
 import org.elasticsearch.client.ml.GetInfluencersRequest;
 import org.elasticsearch.client.ml.GetJobRequest;
 import org.elasticsearch.client.ml.GetJobStatsRequest;
@@ -55,6 +56,7 @@ import org.elasticsearch.client.ml.StartDatafeedRequest;
 import org.elasticsearch.client.ml.StopDatafeedRequest;
 import org.elasticsearch.client.ml.UpdateDatafeedRequest;
 import org.elasticsearch.client.ml.UpdateJobRequest;
+import org.elasticsearch.client.ml.job.util.PageParams;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.bytes.BytesReference;
 
@@ -476,4 +478,22 @@ final class MLRequestConverters {
         request.setEntity(createEntity(putFilterRequest, REQUEST_BODY_CONTENT_TYPE));
         return request;
     }
+
+    static Request getFilter(GetFiltersRequest getFiltersRequest) {
+        String endpoint = new EndpointBuilder()
+            .addPathPartAsIs("_xpack")
+            .addPathPartAsIs("ml")
+            .addPathPartAsIs("filters")
+            .addPathPart(getFiltersRequest.getFilterId())
+            .build();
+        Request request = new Request(HttpGet.METHOD_NAME, endpoint);
+        RequestConverters.Params params = new RequestConverters.Params(request);
+        if (getFiltersRequest.getSize() != null) {
+            params.putParam(PageParams.SIZE.getPreferredName(), getFiltersRequest.getSize().toString());
+        }
+        if (getFiltersRequest.getFrom() != null) {
+            params.putParam(PageParams.FROM.getPreferredName(), getFiltersRequest.getFrom().toString());
+        }
+        return request;
+    }
 }

+ 39 - 0
client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java

@@ -41,6 +41,8 @@ import org.elasticsearch.client.ml.GetDatafeedRequest;
 import org.elasticsearch.client.ml.GetDatafeedResponse;
 import org.elasticsearch.client.ml.GetDatafeedStatsRequest;
 import org.elasticsearch.client.ml.GetDatafeedStatsResponse;
+import org.elasticsearch.client.ml.GetFiltersRequest;
+import org.elasticsearch.client.ml.GetFiltersResponse;
 import org.elasticsearch.client.ml.GetInfluencersRequest;
 import org.elasticsearch.client.ml.GetInfluencersResponse;
 import org.elasticsearch.client.ml.GetJobRequest;
@@ -1207,4 +1209,41 @@ public final class MachineLearningClient {
             Collections.emptySet());
     }
 
+    /**
+     * Gets Machine Learning Filters
+     * <p>
+     * For additional info
+     * see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-filter.html">ML GET Filter documentation</a>
+     *
+     * @param request The request
+     * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+     * @return GetFilterResponse with enclosed {@link org.elasticsearch.client.ml.job.config.MlFilter} objects
+     * @throws IOException when there is a serialization issue sending the request or receiving the response
+     */
+    public GetFiltersResponse getFilter(GetFiltersRequest request, RequestOptions options) throws IOException {
+        return restHighLevelClient.performRequestAndParseEntity(request,
+            MLRequestConverters::getFilter,
+            options,
+            GetFiltersResponse::fromXContent,
+            Collections.emptySet());
+    }
+
+    /**
+     * Gets Machine Learning Filters asynchronously and notifies listener on completion
+     * <p>
+     * For additional info
+     * see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-filter.html">ML GET Filter documentation</a>
+     *
+     * @param request  The request
+     * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+     * @param listener Listener to be notified upon request completion
+     */
+    public void getFilterAsync(GetFiltersRequest request, RequestOptions options, ActionListener<GetFiltersResponse> listener) {
+        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+            MLRequestConverters::getFilter,
+            options,
+            GetFiltersResponse::fromXContent,
+            listener,
+            Collections.emptySet());
+    }
 }

+ 125 - 0
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetFiltersRequest.java

@@ -0,0 +1,125 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch 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.elasticsearch.client.ml;
+
+import org.elasticsearch.action.ActionRequest;
+import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.ml.job.config.MlFilter;
+import org.elasticsearch.client.ml.job.util.PageParams;
+import org.elasticsearch.common.xcontent.ObjectParser;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * A request to retrieve {@link MlFilter}s
+ */
+public class GetFiltersRequest extends ActionRequest implements ToXContentObject {
+
+    public static final ObjectParser<GetFiltersRequest, Void> PARSER =
+        new ObjectParser<>("get_filters_request", GetFiltersRequest::new);
+
+    static {
+        PARSER.declareString(GetFiltersRequest::setFilterId, MlFilter.ID);
+        PARSER.declareInt(GetFiltersRequest::setFrom, PageParams.FROM);
+        PARSER.declareInt(GetFiltersRequest::setSize, PageParams.SIZE);
+    }
+
+    private String filterId;
+    private Integer from;
+    private Integer size;
+
+    public String getFilterId() {
+        return filterId;
+    }
+
+    public Integer getFrom() {
+        return from;
+    }
+
+    public Integer getSize() {
+        return size;
+    }
+
+    /**
+     * Sets the filter id
+     * @param filterId the filter id
+     */
+    public void setFilterId(String filterId) {
+        this.filterId = filterId;
+    }
+
+    /**
+     * Sets the number of filters to skip.
+     * @param from set the `from` parameter
+     */
+    public void setFrom(Integer from) {
+        this.from = from;
+    }
+
+    /**
+     * Sets the number of filters to return.
+     * @param size set the `size` parameter
+     */
+    public void setSize(Integer size) {
+        this.size = size;
+    }
+
+    @Override
+    public ActionRequestValidationException validate() {
+        return null;
+    }
+
+    @Override
+    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+        builder.startObject();
+        if (filterId != null) {
+            builder.field(MlFilter.ID.getPreferredName(), filterId);
+        }
+        if (from != null) {
+            builder.field(PageParams.FROM.getPreferredName(), from);
+        }
+        if (size != null) {
+            builder.field(PageParams.SIZE.getPreferredName(), size);
+        }
+        builder.endObject();
+        return builder;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        GetFiltersRequest request = (GetFiltersRequest) obj;
+        return Objects.equals(filterId, request.filterId)
+            && Objects.equals(from, request.from)
+            && Objects.equals(size, request.size);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(filterId, from, size);
+    }
+}

+ 89 - 0
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetFiltersResponse.java

@@ -0,0 +1,89 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch 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.elasticsearch.client.ml;
+
+import org.elasticsearch.client.ml.job.config.MlFilter;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.Strings;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.XContentParser;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
+
+/**
+ * Contains a {@link List} of the found {@link MlFilter} objects and the total count found
+ */
+public class GetFiltersResponse extends AbstractResultResponse<MlFilter> {
+
+    public static final ParseField RESULTS_FIELD = new ParseField("filters");
+
+    @SuppressWarnings("unchecked")
+    public static final ConstructingObjectParser<GetFiltersResponse, Void> PARSER =
+        new ConstructingObjectParser<>("get_filters_response", true,
+            a -> new GetFiltersResponse((List<MlFilter.Builder>) a[0], (long) a[1]));
+
+    static {
+        PARSER.declareObjectArray(constructorArg(), MlFilter.PARSER, RESULTS_FIELD);
+        PARSER.declareLong(constructorArg(), AbstractResultResponse.COUNT);
+    }
+
+    GetFiltersResponse(List<MlFilter.Builder> filters, long count) {
+        super(RESULTS_FIELD, filters.stream().map(MlFilter.Builder::build).collect(Collectors.toList()), count);
+    }
+
+    /**
+     * The collection of {@link MlFilter} objects found in the query
+     */
+    public List<MlFilter> filters() {
+        return results;
+    }
+
+    public static GetFiltersResponse fromXContent(XContentParser parser) throws IOException {
+        return PARSER.parse(parser, null);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(results, count);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+
+        GetFiltersResponse other = (GetFiltersResponse) obj;
+        return Objects.equals(results, other.results) && count == other.count;
+    }
+
+    @Override
+    public final String toString() {
+        return Strings.toString(this);
+    }
+}

+ 23 - 1
client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java

@@ -35,6 +35,7 @@ import org.elasticsearch.client.ml.GetCalendarsRequest;
 import org.elasticsearch.client.ml.GetCategoriesRequest;
 import org.elasticsearch.client.ml.GetDatafeedRequest;
 import org.elasticsearch.client.ml.GetDatafeedStatsRequest;
+import org.elasticsearch.client.ml.GetFiltersRequest;
 import org.elasticsearch.client.ml.GetInfluencersRequest;
 import org.elasticsearch.client.ml.GetJobRequest;
 import org.elasticsearch.client.ml.GetJobStatsRequest;
@@ -77,6 +78,8 @@ import java.util.HashMap;
 import java.util.Map;
 
 import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.core.IsNull.nullValue;
 
 public class MLRequestConvertersTests extends ESTestCase {
 
@@ -515,7 +518,7 @@ public class MLRequestConvertersTests extends ESTestCase {
     }
 
     public void testPutFilter() throws IOException {
-        MlFilter filter = MlFilterTests.createRandom("foo");
+        MlFilter filter = MlFilterTests.createRandomBuilder("foo").build();
         PutFilterRequest putFilterRequest = new PutFilterRequest(filter);
 
         Request request = MLRequestConverters.putFilter(putFilterRequest);
@@ -528,6 +531,25 @@ public class MLRequestConvertersTests extends ESTestCase {
         }
     }
 
+    public void testGetFilter() throws IOException {
+        String id = randomAlphaOfLength(10);
+        GetFiltersRequest getFiltersRequest = new GetFiltersRequest();
+
+        getFiltersRequest.setFilterId(id);
+
+        Request request = MLRequestConverters.getFilter(getFiltersRequest);
+        assertEquals(HttpGet.METHOD_NAME, request.getMethod());
+        assertEquals("/_xpack/ml/filters/" + id, request.getEndpoint());
+        assertThat(request.getParameters().get(PageParams.FROM.getPreferredName()), is(nullValue()));
+        assertThat(request.getParameters().get(PageParams.SIZE.getPreferredName()), is(nullValue()));
+
+        getFiltersRequest.setFrom(1);
+        getFiltersRequest.setSize(10);
+        request = MLRequestConverters.getFilter(getFiltersRequest);
+        assertThat(request.getParameters().get(PageParams.FROM.getPreferredName()), equalTo("1"));
+        assertThat(request.getParameters().get(PageParams.SIZE.getPreferredName()), equalTo("10"));
+    }
+
     private static Job createValidJob(String jobId) {
         AnalysisConfig.Builder analysisConfig = AnalysisConfig.builder(Collections.singletonList(
                 Detector.builder().setFunction("count").build()));

+ 50 - 1
client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java

@@ -44,6 +44,8 @@ import org.elasticsearch.client.ml.GetDatafeedRequest;
 import org.elasticsearch.client.ml.GetDatafeedResponse;
 import org.elasticsearch.client.ml.GetDatafeedStatsRequest;
 import org.elasticsearch.client.ml.GetDatafeedStatsResponse;
+import org.elasticsearch.client.ml.GetFiltersRequest;
+import org.elasticsearch.client.ml.GetFiltersResponse;
 import org.elasticsearch.client.ml.GetJobRequest;
 import org.elasticsearch.client.ml.GetJobResponse;
 import org.elasticsearch.client.ml.GetJobStatsRequest;
@@ -862,7 +864,7 @@ public class MachineLearningIT extends ESRestHighLevelClientTestCase {
         assertThat(exception.status().getStatus(), equalTo(404));
     }
 
-    public void testFilterJob() throws Exception {
+    public void testPutFilter() throws Exception {
         String filterId = "filter-job-test";
         MlFilter mlFilter = MlFilter.builder(filterId)
             .setDescription(randomAlphaOfLength(10))
@@ -878,6 +880,53 @@ public class MachineLearningIT extends ESRestHighLevelClientTestCase {
         assertThat(createdFilter, equalTo(mlFilter));
     }
 
+    public void testGetFilters() throws Exception {
+        String filterId1 = "get-filter-test-1";
+        String filterId2 = "get-filter-test-2";
+        String filterId3 = "get-filter-test-3";
+        MlFilter mlFilter1 = MlFilter.builder(filterId1)
+            .setDescription(randomAlphaOfLength(10))
+            .setItems(generateRandomStringArray(10, 10, false, false))
+            .build();
+        MlFilter mlFilter2 = MlFilter.builder(filterId2)
+            .setDescription(randomAlphaOfLength(10))
+            .setItems(generateRandomStringArray(10, 10, false, false))
+            .build();
+        MlFilter mlFilter3 = MlFilter.builder(filterId3)
+            .setDescription(randomAlphaOfLength(10))
+            .setItems(generateRandomStringArray(10, 10, false, false))
+            .build();
+        MachineLearningClient machineLearningClient = highLevelClient().machineLearning();
+        machineLearningClient.putFilter(new PutFilterRequest(mlFilter1), RequestOptions.DEFAULT);
+        machineLearningClient.putFilter(new PutFilterRequest(mlFilter2), RequestOptions.DEFAULT);
+        machineLearningClient.putFilter(new PutFilterRequest(mlFilter3), RequestOptions.DEFAULT);
+
+        {
+            GetFiltersRequest getFiltersRequest = new GetFiltersRequest();
+            getFiltersRequest.setFilterId(filterId1);
+
+            GetFiltersResponse getFiltersResponse = execute(getFiltersRequest,
+                machineLearningClient::getFilter,
+                machineLearningClient::getFilterAsync);
+            assertThat(getFiltersResponse.count(), equalTo(1L));
+            assertThat(getFiltersResponse.filters().get(0), equalTo(mlFilter1));
+        }
+        {
+            GetFiltersRequest getFiltersRequest = new GetFiltersRequest();
+
+            getFiltersRequest.setFrom(1);
+            getFiltersRequest.setSize(2);
+
+            GetFiltersResponse getFiltersResponse = execute(getFiltersRequest,
+                machineLearningClient::getFilter,
+                machineLearningClient::getFilterAsync);
+            assertThat(getFiltersResponse.count(), equalTo(2L));
+            assertThat(getFiltersResponse.filters().size(), equalTo(2));
+            assertThat(getFiltersResponse.filters().stream().map(MlFilter::getId).collect(Collectors.toList()),
+                containsInAnyOrder("get-filter-test-2", "get-filter-test-3"));
+        }
+    }
+
     public static String randomValidJobId() {
         CodepointSetGenerator generator = new CodepointSetGenerator("abcdefghijklmnopqrstuvwxyz0123456789".toCharArray());
         return generator.ofCodePointsLength(random(), 10, 10);

+ 66 - 0
client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java

@@ -54,6 +54,8 @@ import org.elasticsearch.client.ml.GetDatafeedRequest;
 import org.elasticsearch.client.ml.GetDatafeedResponse;
 import org.elasticsearch.client.ml.GetDatafeedStatsRequest;
 import org.elasticsearch.client.ml.GetDatafeedStatsResponse;
+import org.elasticsearch.client.ml.GetFiltersRequest;
+import org.elasticsearch.client.ml.GetFiltersResponse;
 import org.elasticsearch.client.ml.GetInfluencersRequest;
 import org.elasticsearch.client.ml.GetInfluencersResponse;
 import org.elasticsearch.client.ml.GetJobRequest;
@@ -2064,4 +2066,68 @@ public class MlClientDocumentationIT extends ESRestHighLevelClientTestCase {
             assertTrue(latch.await(30L, TimeUnit.SECONDS));
         }
     }
+
+    public void testGetFilters() throws IOException, InterruptedException {
+        RestHighLevelClient client = highLevelClient();
+        String filterId = "get-filter-doc-test";
+        MlFilter.Builder filterBuilder = MlFilter.builder(filterId).setDescription("test").setItems("*.google.com", "wikipedia.org");
+
+        client.machineLearning().putFilter(new PutFilterRequest(filterBuilder.build()), RequestOptions.DEFAULT);
+
+        {
+            // tag::get-filters-request
+            GetFiltersRequest request = new GetFiltersRequest(); // <1>
+            // end::get-filters-request
+
+            // tag::get-filters-filter-id
+            request.setFilterId("get-filter-doc-test"); // <1>
+            // end::get-filters-filter-id
+
+            // tag::get-filters-page-params
+            request.setFrom(100); // <1>
+            request.setSize(200); // <2>
+            // end::get-filters-page-params
+
+            request.setFrom(null);
+            request.setSize(null);
+
+            // tag::get-filters-execute
+            GetFiltersResponse response = client.machineLearning().getFilter(request, RequestOptions.DEFAULT);
+            // end::get-filters-execute
+
+            // tag::get-filters-response
+            long count = response.count(); // <1>
+            List<MlFilter> filters = response.filters(); // <2>
+            // end::get-filters-response
+            assertEquals(1, filters.size());
+        }
+        {
+            GetFiltersRequest request = new GetFiltersRequest();
+            request.setFilterId(filterId);
+
+            // tag::get-filters-execute-listener
+            ActionListener<GetFiltersResponse> listener = new ActionListener<GetFiltersResponse>() {
+                    @Override
+                    public void onResponse(GetFiltersResponse getfiltersResponse) {
+                        // <1>
+                    }
+
+                    @Override
+                    public void onFailure(Exception e) {
+                        // <2>
+                    }
+                };
+            // end::get-filters-execute-listener
+
+            // Replace the empty listener by a blocking listener in test
+            final CountDownLatch latch = new CountDownLatch(1);
+            listener = new LatchedActionListener<>(listener, latch);
+
+            // tag::get-filters-execute-async
+            client.machineLearning().getFilterAsync(request, RequestOptions.DEFAULT, listener); // <1>
+            // end::get-filters-execute-async
+
+            assertTrue(latch.await(30L, TimeUnit.SECONDS));
+        }
+    }
 }

+ 52 - 0
client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetFiltersRequestTests.java

@@ -0,0 +1,52 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch 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.elasticsearch.client.ml;
+
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.test.AbstractXContentTestCase;
+
+import java.io.IOException;
+
+public class GetFiltersRequestTests extends AbstractXContentTestCase<GetFiltersRequest> {
+
+    @Override
+    protected GetFiltersRequest createTestInstance() {
+        GetFiltersRequest request = new GetFiltersRequest();
+        if (randomBoolean()) {
+            request.setFilterId(randomAlphaOfLength(10));
+        }
+        if (randomBoolean()) {
+            request.setSize(randomInt(100));
+        }
+        if (randomBoolean()) {
+            request.setFrom(randomInt(100));
+        }
+        return request;
+    }
+
+    @Override
+    protected GetFiltersRequest doParseInstance(XContentParser parser) throws IOException {
+        return GetFiltersRequest.PARSER.apply(parser, null);
+    }
+
+    @Override
+    protected boolean supportsUnknownFields() {
+        return false;
+    }
+}

+ 52 - 0
client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetFiltersResponseTests.java

@@ -0,0 +1,52 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch 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.elasticsearch.client.ml;
+
+import org.elasticsearch.client.ml.job.config.MlFilter;
+import org.elasticsearch.client.ml.job.config.MlFilterTests;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.test.AbstractXContentTestCase;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class GetFiltersResponseTests extends AbstractXContentTestCase<GetFiltersResponse> {
+
+    @Override
+    protected GetFiltersResponse createTestInstance() {
+        int count = randomIntBetween(1, 5);
+        List<MlFilter.Builder> results = new ArrayList<>(count);
+        for(int i = 0; i < count; i++) {
+            results.add(MlFilterTests.createRandomBuilder(randomAlphaOfLength(10)));
+        }
+
+        return new GetFiltersResponse(results, count);
+    }
+
+    @Override
+    protected GetFiltersResponse doParseInstance(XContentParser parser) throws IOException {
+        return GetFiltersResponse.fromXContent(parser);
+    }
+
+    @Override
+    protected boolean supportsUnknownFields() {
+        return true;
+    }
+}

+ 3 - 3
client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/config/MlFilterTests.java

@@ -38,10 +38,10 @@ public class MlFilterTests extends AbstractXContentTestCase<MlFilter> {
     }
 
     public static MlFilter createRandom() {
-        return createRandom(randomAlphaOfLength(10));
+        return createRandomBuilder(randomAlphaOfLength(10)).build();
     }
 
-    public static MlFilter createRandom(String filterId) {
+    public static MlFilter.Builder createRandomBuilder(String filterId) {
         String description = null;
         if (randomBoolean()) {
             description = randomAlphaOfLength(20);
@@ -52,7 +52,7 @@ public class MlFilterTests extends AbstractXContentTestCase<MlFilter> {
         for (int i = 0; i < size; i++) {
             items.add(randomAlphaOfLengthBetween(1, 20));
         }
-        return MlFilter.builder(filterId).setDescription(description).setItems(items).build();
+        return MlFilter.builder(filterId).setDescription(description).setItems(items);
     }
 
     @Override

+ 52 - 0
docs/java-rest/high-level/ml/get-filters.asciidoc

@@ -0,0 +1,52 @@
+--
+:api: get-filters
+:request: GetFiltersRequest
+:response: GetFiltersResponse
+--
+[id="{upid}-{api}"]
+=== Get Filters API
+
+The Get Filters API retrieves one or more filter results.
+It accepts a +{request}+ object and responds
+with a +{response}+ object.
+
+[id="{upid}-{api}-request"]
+==== Get Filters Request
+
+A +{request}+ object gets created.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-request]
+--------------------------------------------------
+<1> Constructing a new request
+
+==== Optional Arguments
+The following arguments are optional:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-filter-id]
+--------------------------------------------------
+<1> The id of the filter to get. Otherwise it will return all filters.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-page-params]
+--------------------------------------------------
+<1> `from` specifies the number of filters to skip. Defaults to `0`.
+<2> `size` specifies the maximum number of filters to get. Defaults to `100`.
+
+include::../execution.asciidoc[]
+
+[id="{upid}-{api}-response"]
+==== Get Filters Response
+
+The returned +{response}+ contains the requested filters:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-response]
+--------------------------------------------------
+<1> The count of filters that were matched
+<2> The filters retrieved

+ 2 - 0
docs/java-rest/high-level/supported-apis.asciidoc

@@ -265,6 +265,7 @@ The Java High Level REST Client supports the following Machine Learning APIs:
 * <<{upid}-put-calendar>>
 * <<{upid}-delete-calendar>>
 * <<{upid}-put-filter>>
+* <<{upid}-get-filters>>
 
 include::ml/put-job.asciidoc[]
 include::ml/get-job.asciidoc[]
@@ -294,6 +295,7 @@ include::ml/get-calendars.asciidoc[]
 include::ml/put-calendar.asciidoc[]
 include::ml/delete-calendar.asciidoc[]
 include::ml/put-filter.asciidoc[]
+include::ml/get-filters.asciidoc[]
 
 == Migration APIs