Skip to content

Commit 8f746d4

Browse files
committed
HLRC: Add ML delete filter action (#35382)
* HLRC: Add ML delete filter action It adds delete ML filter action to the high level rest client. Relates #29827
1 parent 4cffbd3 commit 8f746d4

File tree

9 files changed

+289
-10
lines changed

9 files changed

+289
-10
lines changed

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

+10
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.elasticsearch.client.ml.CloseJobRequest;
3131
import org.elasticsearch.client.ml.DeleteCalendarRequest;
3232
import org.elasticsearch.client.ml.DeleteDatafeedRequest;
33+
import org.elasticsearch.client.ml.DeleteFilterRequest;
3334
import org.elasticsearch.client.ml.DeleteForecastRequest;
3435
import org.elasticsearch.client.ml.DeleteJobRequest;
3536
import org.elasticsearch.client.ml.DeleteModelSnapshotRequest;
@@ -537,4 +538,13 @@ static Request updateFilter(UpdateFilterRequest updateFilterRequest) throws IOEx
537538
request.setEntity(createEntity(updateFilterRequest, REQUEST_BODY_CONTENT_TYPE));
538539
return request;
539540
}
541+
542+
static Request deleteFilter(DeleteFilterRequest deleteFilterRequest) {
543+
String endpoint = new EndpointBuilder()
544+
.addPathPartAsIs("_xpack", "ml", "filters")
545+
.addPathPart(deleteFilterRequest.getId())
546+
.build();
547+
Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
548+
return request;
549+
}
540550
}

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

+41
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.elasticsearch.client.ml.CloseJobResponse;
2525
import org.elasticsearch.client.ml.DeleteCalendarRequest;
2626
import org.elasticsearch.client.ml.DeleteDatafeedRequest;
27+
import org.elasticsearch.client.ml.DeleteFilterRequest;
2728
import org.elasticsearch.client.ml.DeleteForecastRequest;
2829
import org.elasticsearch.client.ml.DeleteJobRequest;
2930
import org.elasticsearch.client.ml.DeleteJobResponse;
@@ -1371,4 +1372,44 @@ public void updateFilterAsync(UpdateFilterRequest request, RequestOptions option
13711372
listener,
13721373
Collections.emptySet());
13731374
}
1375+
1376+
/**
1377+
* Deletes the given Machine Learning filter
1378+
* <p>
1379+
* For additional info
1380+
* see <a href="http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-delete-filter.html">
1381+
* ML Delete Filter documentation</a>
1382+
*
1383+
* @param request The request to delete the filter
1384+
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
1385+
* @return action acknowledgement
1386+
* @throws IOException when there is a serialization issue sending the request or receiving the response
1387+
*/
1388+
public AcknowledgedResponse deleteFilter(DeleteFilterRequest request, RequestOptions options) throws IOException {
1389+
return restHighLevelClient.performRequestAndParseEntity(request,
1390+
MLRequestConverters::deleteFilter,
1391+
options,
1392+
AcknowledgedResponse::fromXContent,
1393+
Collections.emptySet());
1394+
}
1395+
1396+
/**
1397+
* Deletes the given Machine Learning filter asynchronously and notifies the listener on completion
1398+
* <p>
1399+
* For additional info
1400+
* see <a href="http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-delete-filter.html">
1401+
* ML Delete Filter documentation</a>
1402+
*
1403+
* @param request The request to delete the filter
1404+
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
1405+
* @param listener Listener to be notified upon request completion
1406+
*/
1407+
public void deleteFilterAsync(DeleteFilterRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
1408+
restHighLevelClient.performRequestAsyncAndParseEntity(request,
1409+
MLRequestConverters::deleteFilter,
1410+
options,
1411+
AcknowledgedResponse::fromXContent,
1412+
listener,
1413+
Collections.emptySet());
1414+
}
13741415
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.elasticsearch.client.ml;
20+
21+
import org.elasticsearch.client.Validatable;
22+
23+
import java.util.Objects;
24+
25+
/**
26+
* A request to delete a machine learning filter
27+
*/
28+
public class DeleteFilterRequest implements Validatable {
29+
30+
private final String filterId;
31+
32+
public DeleteFilterRequest(String filterId) {
33+
this.filterId = Objects.requireNonNull(filterId, "[filter_id] is required");
34+
}
35+
36+
public String getId() {
37+
return filterId;
38+
}
39+
40+
@Override
41+
public int hashCode() {
42+
return Objects.hash(filterId);
43+
}
44+
45+
@Override
46+
public boolean equals(Object obj) {
47+
if (this == obj) {
48+
return true;
49+
}
50+
if (obj == null) {
51+
return false;
52+
}
53+
if (getClass() != obj.getClass()) {
54+
return false;
55+
}
56+
final DeleteFilterRequest other = (DeleteFilterRequest) obj;
57+
58+
return Objects.equals(filterId, other.filterId);
59+
}
60+
}

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

+12
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.elasticsearch.client.ml.CloseJobRequest;
2727
import org.elasticsearch.client.ml.DeleteCalendarRequest;
2828
import org.elasticsearch.client.ml.DeleteDatafeedRequest;
29+
import org.elasticsearch.client.ml.DeleteFilterRequest;
2930
import org.elasticsearch.client.ml.DeleteForecastRequest;
3031
import org.elasticsearch.client.ml.DeleteJobRequest;
3132
import org.elasticsearch.client.ml.DeleteModelSnapshotRequest;
@@ -596,6 +597,17 @@ public void testUpdateFilter() throws IOException {
596597
}
597598
}
598599

600+
public void testDeleteFilter() {
601+
MlFilter filter = MlFilterTests.createRandomBuilder("foo").build();
602+
DeleteFilterRequest deleteFilterRequest = new DeleteFilterRequest(filter.getId());
603+
604+
Request request = MLRequestConverters.deleteFilter(deleteFilterRequest);
605+
606+
assertEquals(HttpDelete.METHOD_NAME, request.getMethod());
607+
assertThat(request.getEndpoint(), equalTo("/_xpack/ml/filters/foo"));
608+
assertNull(request.getEntity());
609+
}
610+
599611
private static Job createValidJob(String jobId) {
600612
AnalysisConfig.Builder analysisConfig = AnalysisConfig.builder(Collections.singletonList(
601613
Detector.builder().setFunction("count").build()));

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

+27
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.elasticsearch.client.ml.CloseJobResponse;
3232
import org.elasticsearch.client.ml.DeleteCalendarRequest;
3333
import org.elasticsearch.client.ml.DeleteDatafeedRequest;
34+
import org.elasticsearch.client.ml.DeleteFilterRequest;
3435
import org.elasticsearch.client.ml.DeleteForecastRequest;
3536
import org.elasticsearch.client.ml.DeleteJobRequest;
3637
import org.elasticsearch.client.ml.DeleteJobResponse;
@@ -952,6 +953,32 @@ public void testUpdateFilter() throws Exception {
952953
assertThat(filter.getItems(), contains("newItem1", "newItem2", "olditem2"));
953954
}
954955

956+
public void testDeleteFilter() throws Exception {
957+
String filterId = "delete-filter-job-test";
958+
MlFilter mlFilter = MlFilter.builder(filterId)
959+
.setDescription(randomAlphaOfLength(10))
960+
.setItems(generateRandomStringArray(10, 10, false, false))
961+
.build();
962+
MachineLearningClient machineLearningClient = highLevelClient().machineLearning();
963+
964+
PutFilterResponse putFilterResponse = execute(new PutFilterRequest(mlFilter),
965+
machineLearningClient::putFilter,
966+
machineLearningClient::putFilterAsync);
967+
MlFilter createdFilter = putFilterResponse.getResponse();
968+
969+
assertThat(createdFilter, equalTo(mlFilter));
970+
971+
DeleteFilterRequest deleteFilterRequest = new DeleteFilterRequest(filterId);
972+
AcknowledgedResponse response = execute(deleteFilterRequest, machineLearningClient::deleteFilter,
973+
machineLearningClient::deleteFilterAsync);
974+
assertTrue(response.isAcknowledged());
975+
976+
ElasticsearchStatusException exception = expectThrows(ElasticsearchStatusException.class,
977+
() -> execute(deleteFilterRequest, machineLearningClient::deleteFilter,
978+
machineLearningClient::deleteFilterAsync));
979+
assertThat(exception.status().getStatus(), equalTo(404));
980+
}
981+
955982
public static String randomValidJobId() {
956983
CodepointSetGenerator generator = new CodepointSetGenerator("abcdefghijklmnopqrstuvwxyz0123456789".toCharArray());
957984
return generator.ofCodePointsLength(random(), 10, 10);

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

+68-9
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.elasticsearch.client.ml.CloseJobResponse;
3838
import org.elasticsearch.client.ml.DeleteCalendarRequest;
3939
import org.elasticsearch.client.ml.DeleteDatafeedRequest;
40+
import org.elasticsearch.client.ml.DeleteFilterRequest;
4041
import org.elasticsearch.client.ml.DeleteForecastRequest;
4142
import org.elasticsearch.client.ml.DeleteJobRequest;
4243
import org.elasticsearch.client.ml.DeleteJobResponse;
@@ -2284,16 +2285,16 @@ public void testGetFilters() throws IOException, InterruptedException {
22842285

22852286
// tag::get-filters-execute-listener
22862287
ActionListener<GetFiltersResponse> listener = new ActionListener<GetFiltersResponse>() {
2287-
@Override
2288-
public void onResponse(GetFiltersResponse getfiltersResponse) {
2289-
// <1>
2290-
}
2288+
@Override
2289+
public void onResponse(GetFiltersResponse getfiltersResponse) {
2290+
// <1>
2291+
}
22912292

2292-
@Override
2293-
public void onFailure(Exception e) {
2294-
// <2>
2295-
}
2296-
};
2293+
@Override
2294+
public void onFailure(Exception e) {
2295+
// <2>
2296+
}
2297+
};
22972298
// end::get-filters-execute-listener
22982299

22992300
// Replace the empty listener by a blocking listener in test
@@ -2369,4 +2370,62 @@ public void onFailure(Exception e) {
23692370
assertTrue(latch.await(30L, TimeUnit.SECONDS));
23702371
}
23712372
}
2373+
2374+
public void testDeleteFilter() throws Exception {
2375+
RestHighLevelClient client = highLevelClient();
2376+
String filterId = createFilter(client);
2377+
2378+
{
2379+
// tag::delete-filter-request
2380+
DeleteFilterRequest request = new DeleteFilterRequest(filterId); // <1>
2381+
// end::delete-filter-request
2382+
2383+
// tag::delete-filter-execute
2384+
AcknowledgedResponse response = client.machineLearning().deleteFilter(request, RequestOptions.DEFAULT);
2385+
// end::delete-filter-execute
2386+
2387+
// tag::delete-filter-response
2388+
boolean isAcknowledged = response.isAcknowledged(); // <1>
2389+
// end::delete-filter-response
2390+
assertTrue(isAcknowledged);
2391+
}
2392+
filterId = createFilter(client);
2393+
{
2394+
DeleteFilterRequest request = new DeleteFilterRequest(filterId);
2395+
// tag::delete-filter-execute-listener
2396+
ActionListener<AcknowledgedResponse> listener = new ActionListener<AcknowledgedResponse>() {
2397+
@Override
2398+
public void onResponse(AcknowledgedResponse response) {
2399+
// <1>
2400+
}
2401+
2402+
@Override
2403+
public void onFailure(Exception e) {
2404+
// <2>
2405+
}
2406+
};
2407+
// end::delete-filter-execute-listener
2408+
2409+
// Replace the empty listener by a blocking listener in test
2410+
final CountDownLatch latch = new CountDownLatch(1);
2411+
listener = new LatchedActionListener<>(listener, latch);
2412+
2413+
// tag::delete-filter-execute-async
2414+
client.machineLearning().deleteFilterAsync(request, RequestOptions.DEFAULT, listener); //<1>
2415+
// end::delete-filter-execute-async
2416+
2417+
assertTrue(latch.await(30L, TimeUnit.SECONDS));
2418+
}
2419+
}
2420+
2421+
private String createFilter(RestHighLevelClient client) throws IOException {
2422+
MlFilter.Builder filterBuilder = MlFilter.builder("my_safe_domains")
2423+
.setDescription("A list of safe domains")
2424+
.setItems("*.google.com", "wikipedia.org");
2425+
PutFilterRequest putFilterRequest = new PutFilterRequest(filterBuilder.build());
2426+
PutFilterResponse putFilterResponse = client.machineLearning().putFilter(putFilterRequest, RequestOptions.DEFAULT);
2427+
MlFilter createdFilter = putFilterResponse.getResponse();
2428+
assertThat(createdFilter.getId(), equalTo("my_safe_domains"));
2429+
return createdFilter.getId();
2430+
}
23722431
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.elasticsearch.client.ml;
20+
21+
import org.elasticsearch.test.ESTestCase;
22+
23+
public class DeleteFilterRequestTests extends ESTestCase {
24+
25+
public void test_WithNullFilter() {
26+
NullPointerException ex = expectThrows(NullPointerException.class, () -> new DeleteFilterRequest(null));
27+
assertEquals("[filter_id] is required", ex.getMessage());
28+
}
29+
30+
public void test_instance() {
31+
String filterId = randomAlphaOfLengthBetween(2, 10);
32+
DeleteFilterRequest deleteFilterRequest = new DeleteFilterRequest(filterId);
33+
assertEquals(deleteFilterRequest.getId(), filterId);
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--
2+
:api: delete-filter
3+
:request: DeleteFilterRequest
4+
:response: AcknowledgedResponse
5+
--
6+
[id="{upid}-{api}"]
7+
=== Delete Filter API
8+
Delete a {ml} filter.
9+
The API accepts a +{request}+ and responds
10+
with a +{response}+ object.
11+
12+
[id="{upid}-{api}-request"]
13+
==== Delete Filter Request
14+
15+
A +{request}+ object requires a non-null `filterId`.
16+
17+
["source","java",subs="attributes,callouts,macros"]
18+
---------------------------------------------------
19+
include-tagged::{doc-tests-file}[{api}-request]
20+
---------------------------------------------------
21+
<1> Constructing a new request referencing an existing filter
22+
23+
[id="{upid}-{api}-response"]
24+
==== Delete Filter Response
25+
26+
The returned +{response}+ object indicates the acknowledgement of the request:
27+
["source","java",subs="attributes,callouts,macros"]
28+
---------------------------------------------------
29+
include-tagged::{doc-tests-file}[{api}-response]
30+
---------------------------------------------------
31+
<1> `isAcknowledged` was the deletion request acknowledged or not
32+
33+
include::../execution.asciidoc[]

docs/java-rest/high-level/supported-apis.asciidoc

+3-1
Original file line numberDiff line numberDiff line change
@@ -265,10 +265,11 @@ The Java High Level REST Client supports the following Machine Learning APIs:
265265
* <<{upid}-put-calendar>>
266266
* <<{upid}-delete-calendar>>
267267
* <<{upid}-put-filter>>
268-
* <<{upid}-get-model-snapshots>>
269268
* <<{upid}-get-filters>>
270269
* <<{upid}-delete-model-snapshot>>
271270
* <<{upid}-update-filter>>
271+
* <<{upid}-delete-filter>>
272+
* <<{upid}-get-model-snapshots>>
272273

273274
include::ml/put-job.asciidoc[]
274275
include::ml/get-job.asciidoc[]
@@ -302,6 +303,7 @@ include::ml/get-model-snapshots.asciidoc[]
302303
include::ml/get-filters.asciidoc[]
303304
include::ml/delete-model-snapshot.asciidoc[]
304305
include::ml/update-filter.asciidoc[]
306+
include::ml/delete-filter.asciidoc[]
305307

306308
== Migration APIs
307309

0 commit comments

Comments
 (0)