parent
9f8dff9281
commit
27e07ec859
|
@ -28,6 +28,7 @@ import org.apache.http.entity.ByteArrayEntity;
|
|||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.client.RequestConverters.EndpointBuilder;
|
||||
import org.elasticsearch.client.ml.CloseJobRequest;
|
||||
import org.elasticsearch.client.ml.DeleteForecastRequest;
|
||||
import org.elasticsearch.client.ml.DeleteJobRequest;
|
||||
import org.elasticsearch.client.ml.FlushJobRequest;
|
||||
import org.elasticsearch.client.ml.ForecastJobRequest;
|
||||
|
@ -181,6 +182,26 @@ final class MLRequestConverters {
|
|||
return request;
|
||||
}
|
||||
|
||||
static Request deleteForecast(DeleteForecastRequest deleteForecastRequest) throws IOException {
|
||||
String endpoint = new EndpointBuilder()
|
||||
.addPathPartAsIs("_xpack")
|
||||
.addPathPartAsIs("ml")
|
||||
.addPathPartAsIs("anomaly_detectors")
|
||||
.addPathPart(deleteForecastRequest.getJobId())
|
||||
.addPathPartAsIs("_forecast")
|
||||
.addPathPart(Strings.collectionToCommaDelimitedString(deleteForecastRequest.getForecastIds()))
|
||||
.build();
|
||||
Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
|
||||
RequestConverters.Params params = new RequestConverters.Params(request);
|
||||
if (deleteForecastRequest.isAllowNoForecasts() != null) {
|
||||
params.putParam("allow_no_forecasts", Boolean.toString(deleteForecastRequest.isAllowNoForecasts()));
|
||||
}
|
||||
if (deleteForecastRequest.timeout() != null) {
|
||||
params.putParam("timeout", deleteForecastRequest.timeout().getStringRep());
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
static Request getBuckets(GetBucketsRequest getBucketsRequest) throws IOException {
|
||||
String endpoint = new EndpointBuilder()
|
||||
.addPathPartAsIs("_xpack")
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
package org.elasticsearch.client;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
||||
import org.elasticsearch.client.ml.DeleteForecastRequest;
|
||||
import org.elasticsearch.client.ml.ForecastJobRequest;
|
||||
import org.elasticsearch.client.ml.ForecastJobResponse;
|
||||
import org.elasticsearch.client.ml.PostDataRequest;
|
||||
|
@ -389,6 +391,11 @@ public final class MachineLearningClient {
|
|||
/**
|
||||
* Updates a Machine Learning {@link org.elasticsearch.client.ml.job.config.Job}
|
||||
*
|
||||
* <p>
|
||||
* For additional info
|
||||
* see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-update-job.html"></a>
|
||||
* </p>
|
||||
*
|
||||
* @param request the {@link UpdateJobRequest} object enclosing the desired updates
|
||||
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
|
||||
* @return a PutJobResponse object containing the updated job object
|
||||
|
@ -427,6 +434,10 @@ public final class MachineLearningClient {
|
|||
/**
|
||||
* Updates a Machine Learning {@link org.elasticsearch.client.ml.job.config.Job} asynchronously
|
||||
*
|
||||
* <p>
|
||||
* For additional info
|
||||
* see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-update-job.html"></a>
|
||||
* </p>
|
||||
* @param request the {@link UpdateJobRequest} object enclosing the desired updates
|
||||
* @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
|
||||
|
@ -440,6 +451,48 @@ public final class MachineLearningClient {
|
|||
Collections.emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes Machine Learning Job Forecasts
|
||||
*
|
||||
* <p>
|
||||
* For additional info
|
||||
* see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-delete-forecast.html"></a>
|
||||
* </p>
|
||||
*
|
||||
* @param request the {@link DeleteForecastRequest} object enclosing the desired jobId, forecastIDs, and other options
|
||||
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
|
||||
* @return a AcknowledgedResponse object indicating request success
|
||||
* @throws IOException when there is a serialization issue sending the request or receiving the response
|
||||
*/
|
||||
public AcknowledgedResponse deleteForecast(DeleteForecastRequest request, RequestOptions options) throws IOException {
|
||||
return restHighLevelClient.performRequestAndParseEntity(request,
|
||||
MLRequestConverters::deleteForecast,
|
||||
options,
|
||||
AcknowledgedResponse::fromXContent,
|
||||
Collections.emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes Machine Learning Job Forecasts asynchronously
|
||||
*
|
||||
* <p>
|
||||
* For additional info
|
||||
* see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-delete-forecast.html"></a>
|
||||
* </p>
|
||||
*
|
||||
* @param request the {@link DeleteForecastRequest} object enclosing the desired jobId, forecastIDs, and other options
|
||||
* @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 deleteForecastAsync(DeleteForecastRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
|
||||
restHighLevelClient.performRequestAsyncAndParseEntity(request,
|
||||
MLRequestConverters::deleteForecast,
|
||||
options,
|
||||
AcknowledgedResponse::fromXContent,
|
||||
listener,
|
||||
Collections.emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the buckets for a Machine Learning Job.
|
||||
* <p>
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* 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.Job;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* POJO for a delete forecast request
|
||||
*/
|
||||
public class DeleteForecastRequest extends ActionRequest implements ToXContentObject {
|
||||
|
||||
public static final ParseField FORECAST_ID = new ParseField("forecast_id");
|
||||
public static final ParseField ALLOW_NO_FORECASTS = new ParseField("allow_no_forecasts");
|
||||
public static final ParseField TIMEOUT = new ParseField("timeout");
|
||||
public static final String ALL = "_all";
|
||||
|
||||
public static final ConstructingObjectParser<DeleteForecastRequest, Void> PARSER =
|
||||
new ConstructingObjectParser<>("delete_forecast_request", (a) -> new DeleteForecastRequest((String) a[0]));
|
||||
|
||||
static {
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), Job.ID);
|
||||
PARSER.declareStringOrNull(
|
||||
(c, p) -> c.setForecastIds(Strings.commaDelimitedListToStringArray(p)), FORECAST_ID);
|
||||
PARSER.declareBoolean(DeleteForecastRequest::setAllowNoForecasts, ALLOW_NO_FORECASTS);
|
||||
PARSER.declareString(DeleteForecastRequest::timeout, TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link DeleteForecastRequest} that explicitly deletes all forecasts
|
||||
*
|
||||
* @param jobId the jobId of the Job whose forecasts to delete
|
||||
*/
|
||||
public static DeleteForecastRequest deleteAllForecasts(String jobId) {
|
||||
DeleteForecastRequest request = new DeleteForecastRequest(jobId);
|
||||
request.setForecastIds(ALL);
|
||||
return request;
|
||||
}
|
||||
|
||||
private final String jobId;
|
||||
private List<String> forecastIds = new ArrayList<>();
|
||||
private Boolean allowNoForecasts;
|
||||
private TimeValue timeout;
|
||||
|
||||
/**
|
||||
* Create a new DeleteForecastRequest for the given Job ID
|
||||
*
|
||||
* @param jobId the jobId of the Job whose forecast(s) to delete
|
||||
*/
|
||||
public DeleteForecastRequest(String jobId) {
|
||||
this.jobId = Objects.requireNonNull(jobId, Job.ID.getPreferredName());
|
||||
}
|
||||
|
||||
public String getJobId() {
|
||||
return jobId;
|
||||
}
|
||||
|
||||
public List<String> getForecastIds() {
|
||||
return forecastIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* The forecast IDs to delete. Can be also be {@link DeleteForecastRequest#ALL} to explicitly delete ALL forecasts
|
||||
*
|
||||
* @param forecastIds forecast IDs to delete
|
||||
*/
|
||||
public void setForecastIds(String... forecastIds) {
|
||||
setForecastIds(Arrays.asList(forecastIds));
|
||||
}
|
||||
|
||||
void setForecastIds(List<String> forecastIds) {
|
||||
if (forecastIds.stream().anyMatch(Objects::isNull)) {
|
||||
throw new NullPointerException("forecastIds must not contain null values");
|
||||
}
|
||||
this.forecastIds = new ArrayList<>(forecastIds);
|
||||
}
|
||||
|
||||
public Boolean isAllowNoForecasts() {
|
||||
return allowNoForecasts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the `allow_no_forecasts` field.
|
||||
*
|
||||
* @param allowNoForecasts when {@code true} no error is thrown when {@link DeleteForecastRequest#ALL} does not find any forecasts
|
||||
*/
|
||||
public void setAllowNoForecasts(boolean allowNoForecasts) {
|
||||
this.allowNoForecasts = allowNoForecasts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to set the timeout
|
||||
* @param timeout timeout as a string (e.g. 1s)
|
||||
*/
|
||||
public void timeout(String timeout) {
|
||||
this.timeout = TimeValue.parseTimeValue(timeout, this.timeout, getClass().getSimpleName() + ".timeout");
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to set the timeout
|
||||
* @param timeout timeout as a {@link TimeValue}
|
||||
*/
|
||||
public void timeout(TimeValue timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public TimeValue timeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (other == null || getClass() != other.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DeleteForecastRequest that = (DeleteForecastRequest) other;
|
||||
return Objects.equals(jobId, that.jobId) &&
|
||||
Objects.equals(forecastIds, that.forecastIds) &&
|
||||
Objects.equals(allowNoForecasts, that.allowNoForecasts) &&
|
||||
Objects.equals(timeout, that.timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(jobId, forecastIds, allowNoForecasts, timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionRequestValidationException validate() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(Job.ID.getPreferredName(), jobId);
|
||||
if (forecastIds != null) {
|
||||
builder.field(FORECAST_ID.getPreferredName(), Strings.collectionToCommaDelimitedString(forecastIds));
|
||||
}
|
||||
if (allowNoForecasts != null) {
|
||||
builder.field(ALLOW_NO_FORECASTS.getPreferredName(), allowNoForecasts);
|
||||
}
|
||||
if (timeout != null) {
|
||||
builder.field(TIMEOUT.getPreferredName(), timeout.getStringRep());
|
||||
}
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ import org.apache.http.client.methods.HttpGet;
|
|||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.elasticsearch.client.ml.CloseJobRequest;
|
||||
import org.elasticsearch.client.ml.DeleteForecastRequest;
|
||||
import org.elasticsearch.client.ml.DeleteJobRequest;
|
||||
import org.elasticsearch.client.ml.FlushJobRequest;
|
||||
import org.elasticsearch.client.ml.ForecastJobRequest;
|
||||
|
@ -44,6 +45,7 @@ import org.elasticsearch.client.ml.job.config.Job;
|
|||
import org.elasticsearch.client.ml.job.config.JobUpdate;
|
||||
import org.elasticsearch.client.ml.job.config.JobUpdateTests;
|
||||
import org.elasticsearch.client.ml.job.util.PageParams;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
|
@ -204,6 +206,33 @@ public class MLRequestConvertersTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testDeleteForecast() throws Exception {
|
||||
String jobId = randomAlphaOfLength(10);
|
||||
DeleteForecastRequest deleteForecastRequest = new DeleteForecastRequest(jobId);
|
||||
|
||||
Request request = MLRequestConverters.deleteForecast(deleteForecastRequest);
|
||||
assertEquals(HttpDelete.METHOD_NAME, request.getMethod());
|
||||
assertEquals("/_xpack/ml/anomaly_detectors/" + jobId + "/_forecast", request.getEndpoint());
|
||||
assertFalse(request.getParameters().containsKey("timeout"));
|
||||
assertFalse(request.getParameters().containsKey("allow_no_forecasts"));
|
||||
|
||||
deleteForecastRequest.setForecastIds(randomAlphaOfLength(10), randomAlphaOfLength(10));
|
||||
deleteForecastRequest.timeout("10s");
|
||||
deleteForecastRequest.setAllowNoForecasts(true);
|
||||
|
||||
request = MLRequestConverters.deleteForecast(deleteForecastRequest);
|
||||
assertEquals(
|
||||
"/_xpack/ml/anomaly_detectors/" +
|
||||
jobId +
|
||||
"/_forecast/" +
|
||||
Strings.collectionToCommaDelimitedString(deleteForecastRequest.getForecastIds()),
|
||||
request.getEndpoint());
|
||||
assertEquals("10s",
|
||||
request.getParameters().get(DeleteForecastRequest.TIMEOUT.getPreferredName()));
|
||||
assertEquals(Boolean.toString(true),
|
||||
request.getParameters().get(DeleteForecastRequest.ALLOW_NO_FORECASTS.getPreferredName()));
|
||||
}
|
||||
|
||||
public void testGetBuckets() throws IOException {
|
||||
String jobId = randomAlphaOfLength(10);
|
||||
GetBucketsRequest getBucketsRequest = new GetBucketsRequest(jobId);
|
||||
|
|
|
@ -20,6 +20,10 @@ package org.elasticsearch.client;
|
|||
|
||||
import com.carrotsearch.randomizedtesting.generators.CodepointSetGenerator;
|
||||
import org.elasticsearch.ElasticsearchStatusException;
|
||||
import org.elasticsearch.action.get.GetRequest;
|
||||
import org.elasticsearch.action.get.GetResponse;
|
||||
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
||||
import org.elasticsearch.client.ml.DeleteForecastRequest;
|
||||
import org.elasticsearch.client.ml.ForecastJobRequest;
|
||||
import org.elasticsearch.client.ml.ForecastJobResponse;
|
||||
import org.elasticsearch.client.ml.PostDataRequest;
|
||||
|
@ -288,6 +292,75 @@ public class MachineLearningIT extends ESRestHighLevelClientTestCase {
|
|||
assertEquals("Updated description", getResponse.jobs().get(0).getDescription());
|
||||
}
|
||||
|
||||
public void testDeleteForecast() throws Exception {
|
||||
String jobId = "test-delete-forecast";
|
||||
|
||||
Job job = buildJob(jobId);
|
||||
MachineLearningClient machineLearningClient = highLevelClient().machineLearning();
|
||||
machineLearningClient.putJob(new PutJobRequest(job), RequestOptions.DEFAULT);
|
||||
machineLearningClient.openJob(new OpenJobRequest(jobId), RequestOptions.DEFAULT);
|
||||
|
||||
Job noForecastsJob = buildJob("test-delete-forecast-none");
|
||||
machineLearningClient.putJob(new PutJobRequest(noForecastsJob), RequestOptions.DEFAULT);
|
||||
|
||||
PostDataRequest.JsonBuilder builder = new PostDataRequest.JsonBuilder();
|
||||
for(int i = 0; i < 30; i++) {
|
||||
Map<String, Object> hashMap = new HashMap<>();
|
||||
hashMap.put("total", randomInt(1000));
|
||||
hashMap.put("timestamp", (i+1)*1000);
|
||||
builder.addDoc(hashMap);
|
||||
}
|
||||
|
||||
PostDataRequest postDataRequest = new PostDataRequest(jobId, builder);
|
||||
machineLearningClient.postData(postDataRequest, RequestOptions.DEFAULT);
|
||||
machineLearningClient.flushJob(new FlushJobRequest(jobId), RequestOptions.DEFAULT);
|
||||
ForecastJobResponse forecastJobResponse1 = machineLearningClient.forecastJob(new ForecastJobRequest(jobId), RequestOptions.DEFAULT);
|
||||
ForecastJobResponse forecastJobResponse2 = machineLearningClient.forecastJob(new ForecastJobRequest(jobId), RequestOptions.DEFAULT);
|
||||
waitForForecastToComplete(jobId, forecastJobResponse1.getForecastId());
|
||||
waitForForecastToComplete(jobId, forecastJobResponse2.getForecastId());
|
||||
|
||||
{
|
||||
DeleteForecastRequest request = new DeleteForecastRequest(jobId);
|
||||
request.setForecastIds(forecastJobResponse1.getForecastId(), forecastJobResponse2.getForecastId());
|
||||
AcknowledgedResponse response = execute(request, machineLearningClient::deleteForecast,
|
||||
machineLearningClient::deleteForecastAsync);
|
||||
assertTrue(response.isAcknowledged());
|
||||
assertFalse(forecastExists(jobId, forecastJobResponse1.getForecastId()));
|
||||
assertFalse(forecastExists(jobId, forecastJobResponse2.getForecastId()));
|
||||
}
|
||||
{
|
||||
DeleteForecastRequest request = DeleteForecastRequest.deleteAllForecasts(noForecastsJob.getId());
|
||||
request.setAllowNoForecasts(true);
|
||||
AcknowledgedResponse response = execute(request, machineLearningClient::deleteForecast,
|
||||
machineLearningClient::deleteForecastAsync);
|
||||
assertTrue(response.isAcknowledged());
|
||||
}
|
||||
{
|
||||
DeleteForecastRequest request = DeleteForecastRequest.deleteAllForecasts(noForecastsJob.getId());
|
||||
request.setAllowNoForecasts(false);
|
||||
ElasticsearchStatusException exception = expectThrows(ElasticsearchStatusException.class,
|
||||
() -> execute(request, machineLearningClient::deleteForecast, machineLearningClient::deleteForecastAsync));
|
||||
assertThat(exception.status().getStatus(), equalTo(404));
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForForecastToComplete(String jobId, String forecastId) throws Exception {
|
||||
GetRequest request = new GetRequest(".ml-anomalies-" + jobId);
|
||||
request.id(jobId + "_model_forecast_request_stats_" + forecastId);
|
||||
assertBusy(() -> {
|
||||
GetResponse getResponse = highLevelClient().get(request, RequestOptions.DEFAULT);
|
||||
assertTrue(getResponse.isExists());
|
||||
assertTrue(getResponse.getSourceAsString().contains("finished"));
|
||||
}, 30, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private boolean forecastExists(String jobId, String forecastId) throws Exception {
|
||||
GetRequest getRequest = new GetRequest(".ml-anomalies-" + jobId);
|
||||
getRequest.id(jobId + "_model_forecast_request_stats_" + forecastId);
|
||||
GetResponse getResponse = highLevelClient().get(getRequest, RequestOptions.DEFAULT);
|
||||
return getResponse.isExists();
|
||||
}
|
||||
|
||||
public static String randomValidJobId() {
|
||||
CodepointSetGenerator generator = new CodepointSetGenerator("abcdefghijklmnopqrstuvwxyz0123456789".toCharArray());
|
||||
return generator.ofCodePointsLength(random(), 10, 10);
|
||||
|
|
|
@ -21,8 +21,11 @@ package org.elasticsearch.client.documentation;
|
|||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.LatchedActionListener;
|
||||
import org.elasticsearch.action.bulk.BulkRequest;
|
||||
import org.elasticsearch.action.get.GetRequest;
|
||||
import org.elasticsearch.action.get.GetResponse;
|
||||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.support.WriteRequest;
|
||||
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
||||
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
|
||||
import org.elasticsearch.client.MachineLearningGetResultsIT;
|
||||
import org.elasticsearch.client.MachineLearningIT;
|
||||
|
@ -31,6 +34,7 @@ import org.elasticsearch.client.RequestOptions;
|
|||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.elasticsearch.client.ml.CloseJobRequest;
|
||||
import org.elasticsearch.client.ml.CloseJobResponse;
|
||||
import org.elasticsearch.client.ml.DeleteForecastRequest;
|
||||
import org.elasticsearch.client.ml.DeleteJobRequest;
|
||||
import org.elasticsearch.client.ml.DeleteJobResponse;
|
||||
import org.elasticsearch.client.ml.FlushJobRequest;
|
||||
|
@ -639,8 +643,85 @@ public class MlClientDocumentationIT extends ESRestHighLevelClientTestCase {
|
|||
assertTrue(latch.await(30L, TimeUnit.SECONDS));
|
||||
}
|
||||
}
|
||||
|
||||
public void testDeleteForecast() throws Exception {
|
||||
RestHighLevelClient client = highLevelClient();
|
||||
|
||||
Job job = MachineLearningIT.buildJob("deleting-forecast-for-job");
|
||||
client.machineLearning().putJob(new PutJobRequest(job), RequestOptions.DEFAULT);
|
||||
client.machineLearning().openJob(new OpenJobRequest(job.getId()), RequestOptions.DEFAULT);
|
||||
PostDataRequest.JsonBuilder builder = new PostDataRequest.JsonBuilder();
|
||||
for(int i = 0; i < 30; i++) {
|
||||
Map<String, Object> hashMap = new HashMap<>();
|
||||
hashMap.put("total", randomInt(1000));
|
||||
hashMap.put("timestamp", (i+1)*1000);
|
||||
builder.addDoc(hashMap);
|
||||
}
|
||||
|
||||
PostDataRequest postDataRequest = new PostDataRequest(job.getId(), builder);
|
||||
client.machineLearning().postData(postDataRequest, RequestOptions.DEFAULT);
|
||||
client.machineLearning().flushJob(new FlushJobRequest(job.getId()), RequestOptions.DEFAULT);
|
||||
ForecastJobResponse forecastJobResponse = client.machineLearning().
|
||||
forecastJob(new ForecastJobRequest(job.getId()), RequestOptions.DEFAULT);
|
||||
String forecastId = forecastJobResponse.getForecastId();
|
||||
|
||||
GetRequest request = new GetRequest(".ml-anomalies-" + job.getId());
|
||||
request.id(job.getId() + "_model_forecast_request_stats_" + forecastId);
|
||||
assertBusy(() -> {
|
||||
GetResponse getResponse = highLevelClient().get(request, RequestOptions.DEFAULT);
|
||||
assertTrue(getResponse.isExists());
|
||||
assertTrue(getResponse.getSourceAsString().contains("finished"));
|
||||
}, 30, TimeUnit.SECONDS);
|
||||
|
||||
{
|
||||
//tag::x-pack-ml-delete-forecast-request
|
||||
DeleteForecastRequest deleteForecastRequest = new DeleteForecastRequest("deleting-forecast-for-job"); //<1>
|
||||
//end::x-pack-ml-delete-forecast-request
|
||||
|
||||
//tag::x-pack-ml-delete-forecast-request-options
|
||||
deleteForecastRequest.setForecastIds(forecastId); //<1>
|
||||
deleteForecastRequest.timeout("30s"); //<2>
|
||||
deleteForecastRequest.setAllowNoForecasts(true); //<3>
|
||||
//end::x-pack-ml-delete-forecast-request-options
|
||||
|
||||
//tag::x-pack-ml-delete-forecast-execute
|
||||
AcknowledgedResponse deleteForecastResponse = client.machineLearning().deleteForecast(deleteForecastRequest,
|
||||
RequestOptions.DEFAULT);
|
||||
//end::x-pack-ml-delete-forecast-execute
|
||||
|
||||
//tag::x-pack-ml-delete-forecast-response
|
||||
boolean isAcknowledged = deleteForecastResponse.isAcknowledged(); //<1>
|
||||
//end::x-pack-ml-delete-forecast-response
|
||||
}
|
||||
{
|
||||
//tag::x-pack-ml-delete-forecast-listener
|
||||
ActionListener<AcknowledgedResponse> listener = new ActionListener<AcknowledgedResponse>() {
|
||||
@Override
|
||||
public void onResponse(AcknowledgedResponse DeleteForecastResponse) {
|
||||
//<1>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
// <2>
|
||||
}
|
||||
};
|
||||
//end::x-pack-ml-delete-forecast-listener
|
||||
DeleteForecastRequest deleteForecastRequest = DeleteForecastRequest.deleteAllForecasts(job.getId());
|
||||
deleteForecastRequest.setAllowNoForecasts(true);
|
||||
|
||||
// Replace the empty listener by a blocking listener in test
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
listener = new LatchedActionListener<>(listener, latch);
|
||||
|
||||
// tag::x-pack-ml-delete-forecast-execute-async
|
||||
client.machineLearning().deleteForecastAsync(deleteForecastRequest, RequestOptions.DEFAULT, listener); //<1>
|
||||
// end::x-pack-ml-delete-forecast-execute-async
|
||||
|
||||
assertTrue(latch.await(30L, TimeUnit.SECONDS));
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetJobStats() throws Exception {
|
||||
RestHighLevelClient client = highLevelClient();
|
||||
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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.JobTests;
|
||||
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 DeleteForecastRequestTests extends AbstractXContentTestCase<DeleteForecastRequest> {
|
||||
|
||||
@Override
|
||||
protected DeleteForecastRequest createTestInstance() {
|
||||
|
||||
DeleteForecastRequest deleteForecastRequest = new DeleteForecastRequest(JobTests.randomValidJobId());
|
||||
if (randomBoolean()) {
|
||||
int length = randomInt(10);
|
||||
List<String> ids = new ArrayList<>(length);
|
||||
for(int i = 0; i < length; i++) {
|
||||
ids.add(randomAlphaOfLength(10));
|
||||
}
|
||||
deleteForecastRequest.setForecastIds(ids);
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
deleteForecastRequest.setAllowNoForecasts(randomBoolean());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
deleteForecastRequest.timeout(randomTimeValue());
|
||||
}
|
||||
return deleteForecastRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DeleteForecastRequest doParseInstance(XContentParser parser) throws IOException {
|
||||
return DeleteForecastRequest.PARSER.apply(parser, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsUnknownFields() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
[[java-rest-high-x-pack-ml-delete-forecast]]
|
||||
=== Delete Forecast API
|
||||
|
||||
The Delete Forecast API provides the ability to delete a {ml} job's
|
||||
forecast in the cluster.
|
||||
It accepts a `DeleteForecastRequest` object and responds
|
||||
with an `AcknowledgedResponse` object.
|
||||
|
||||
[[java-rest-high-x-pack-ml-delete-forecast-request]]
|
||||
==== Delete Forecast Request
|
||||
|
||||
A `DeleteForecastRequest` object gets created with an existing non-null `jobId`.
|
||||
All other fields are optional for the request.
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-delete-forecast-request]
|
||||
--------------------------------------------------
|
||||
<1> Constructing a new request referencing an existing `jobId`
|
||||
|
||||
==== Optional Arguments
|
||||
|
||||
The following arguments are optional.
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-delete-forecast-request-options]
|
||||
--------------------------------------------------
|
||||
<1> Sets the specific forecastIds to delete, can be set to `_all` to indicate ALL forecasts for the given
|
||||
`jobId`
|
||||
<2> Set the timeout for the request to respond, default is 30 seconds
|
||||
<3> Set the `allow_no_forecasts` option. When `true` no error will be returned if an `_all`
|
||||
request finds no forecasts. It defaults to `true`
|
||||
|
||||
[[java-rest-high-x-pack-ml-delete-forecast-execution]]
|
||||
==== Execution
|
||||
|
||||
The request can be executed through the `MachineLearningClient` contained
|
||||
in the `RestHighLevelClient` object, accessed via the `machineLearningClient()` method.
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-delete-forecast-execute]
|
||||
--------------------------------------------------
|
||||
|
||||
[[java-rest-high-x-pack-ml-delete-forecast-execution-async]]
|
||||
==== Asynchronous Execution
|
||||
|
||||
The request can also be executed asynchronously:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-delete-forecast-execute-async]
|
||||
--------------------------------------------------
|
||||
<1> The `DeleteForecastRequest` to execute and the `ActionListener` to use when
|
||||
the execution completes
|
||||
|
||||
The method does not block and returns immediately. The passed `ActionListener` is used
|
||||
to notify the caller of completion. A typical `ActionListener` for `AcknowledgedResponse` may
|
||||
look like
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-delete-forecast-listener]
|
||||
--------------------------------------------------
|
||||
<1> `onResponse` is called back when the action is completed successfully
|
||||
<2> `onFailure` is called back when some unexpected error occurs
|
||||
|
||||
[[java-rest-high-x-pack-ml-delete-forecast-response]]
|
||||
==== Delete Forecast Response
|
||||
|
||||
An `AcknowledgedResponse` contains an acknowledgement of the forecast(s) deletion
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-delete-forecast-response]
|
||||
--------------------------------------------------
|
||||
<1> `isAcknowledged()` indicates if the forecast was successfully deleted or not.
|
|
@ -221,6 +221,7 @@ The Java High Level REST Client supports the following Machine Learning APIs:
|
|||
* <<java-rest-high-x-pack-ml-update-job>>
|
||||
* <<java-rest-high-x-pack-ml-get-job-stats>>
|
||||
* <<java-rest-high-x-pack-ml-forecast-job>>
|
||||
* <<java-rest-high-x-pack-ml-delete-forecast>>
|
||||
* <<java-rest-high-x-pack-ml-get-buckets>>
|
||||
* <<java-rest-high-x-pack-ml-get-overall-buckets>>
|
||||
* <<java-rest-high-x-pack-ml-get-records>>
|
||||
|
@ -237,6 +238,7 @@ include::ml/update-job.asciidoc[]
|
|||
include::ml/flush-job.asciidoc[]
|
||||
include::ml/get-job-stats.asciidoc[]
|
||||
include::ml/forecast-job.asciidoc[]
|
||||
include::ml/delete-forecast.asciidoc[]
|
||||
include::ml/get-buckets.asciidoc[]
|
||||
include::ml/get-overall-buckets.asciidoc[]
|
||||
include::ml/get-records.asciidoc[]
|
||||
|
|
Loading…
Reference in New Issue