parent
9f8dff9281
commit
27e07ec859
|
@ -28,6 +28,7 @@ import org.apache.http.entity.ByteArrayEntity;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.elasticsearch.client.RequestConverters.EndpointBuilder;
|
import org.elasticsearch.client.RequestConverters.EndpointBuilder;
|
||||||
import org.elasticsearch.client.ml.CloseJobRequest;
|
import org.elasticsearch.client.ml.CloseJobRequest;
|
||||||
|
import org.elasticsearch.client.ml.DeleteForecastRequest;
|
||||||
import org.elasticsearch.client.ml.DeleteJobRequest;
|
import org.elasticsearch.client.ml.DeleteJobRequest;
|
||||||
import org.elasticsearch.client.ml.FlushJobRequest;
|
import org.elasticsearch.client.ml.FlushJobRequest;
|
||||||
import org.elasticsearch.client.ml.ForecastJobRequest;
|
import org.elasticsearch.client.ml.ForecastJobRequest;
|
||||||
|
@ -181,6 +182,26 @@ final class MLRequestConverters {
|
||||||
return request;
|
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 {
|
static Request getBuckets(GetBucketsRequest getBucketsRequest) throws IOException {
|
||||||
String endpoint = new EndpointBuilder()
|
String endpoint = new EndpointBuilder()
|
||||||
.addPathPartAsIs("_xpack")
|
.addPathPartAsIs("_xpack")
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
package org.elasticsearch.client;
|
package org.elasticsearch.client;
|
||||||
|
|
||||||
import org.elasticsearch.action.ActionListener;
|
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.ForecastJobRequest;
|
||||||
import org.elasticsearch.client.ml.ForecastJobResponse;
|
import org.elasticsearch.client.ml.ForecastJobResponse;
|
||||||
import org.elasticsearch.client.ml.PostDataRequest;
|
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}
|
* 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 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 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
|
* @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
|
* 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 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 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
|
* @param listener Listener to be notified upon request completion
|
||||||
|
@ -440,6 +451,48 @@ public final class MachineLearningClient {
|
||||||
Collections.emptySet());
|
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.
|
* Gets the buckets for a Machine Learning Job.
|
||||||
* <p>
|
* <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.HttpPost;
|
||||||
import org.apache.http.client.methods.HttpPut;
|
import org.apache.http.client.methods.HttpPut;
|
||||||
import org.elasticsearch.client.ml.CloseJobRequest;
|
import org.elasticsearch.client.ml.CloseJobRequest;
|
||||||
|
import org.elasticsearch.client.ml.DeleteForecastRequest;
|
||||||
import org.elasticsearch.client.ml.DeleteJobRequest;
|
import org.elasticsearch.client.ml.DeleteJobRequest;
|
||||||
import org.elasticsearch.client.ml.FlushJobRequest;
|
import org.elasticsearch.client.ml.FlushJobRequest;
|
||||||
import org.elasticsearch.client.ml.ForecastJobRequest;
|
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.JobUpdate;
|
||||||
import org.elasticsearch.client.ml.job.config.JobUpdateTests;
|
import org.elasticsearch.client.ml.job.config.JobUpdateTests;
|
||||||
import org.elasticsearch.client.ml.job.util.PageParams;
|
import org.elasticsearch.client.ml.job.util.PageParams;
|
||||||
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
import org.elasticsearch.common.xcontent.XContentParser;
|
import org.elasticsearch.common.xcontent.XContentParser;
|
||||||
import org.elasticsearch.common.xcontent.XContentType;
|
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 {
|
public void testGetBuckets() throws IOException {
|
||||||
String jobId = randomAlphaOfLength(10);
|
String jobId = randomAlphaOfLength(10);
|
||||||
GetBucketsRequest getBucketsRequest = new GetBucketsRequest(jobId);
|
GetBucketsRequest getBucketsRequest = new GetBucketsRequest(jobId);
|
||||||
|
|
|
@ -20,6 +20,10 @@ package org.elasticsearch.client;
|
||||||
|
|
||||||
import com.carrotsearch.randomizedtesting.generators.CodepointSetGenerator;
|
import com.carrotsearch.randomizedtesting.generators.CodepointSetGenerator;
|
||||||
import org.elasticsearch.ElasticsearchStatusException;
|
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.ForecastJobRequest;
|
||||||
import org.elasticsearch.client.ml.ForecastJobResponse;
|
import org.elasticsearch.client.ml.ForecastJobResponse;
|
||||||
import org.elasticsearch.client.ml.PostDataRequest;
|
import org.elasticsearch.client.ml.PostDataRequest;
|
||||||
|
@ -288,6 +292,75 @@ public class MachineLearningIT extends ESRestHighLevelClientTestCase {
|
||||||
assertEquals("Updated description", getResponse.jobs().get(0).getDescription());
|
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() {
|
public static String randomValidJobId() {
|
||||||
CodepointSetGenerator generator = new CodepointSetGenerator("abcdefghijklmnopqrstuvwxyz0123456789".toCharArray());
|
CodepointSetGenerator generator = new CodepointSetGenerator("abcdefghijklmnopqrstuvwxyz0123456789".toCharArray());
|
||||||
return generator.ofCodePointsLength(random(), 10, 10);
|
return generator.ofCodePointsLength(random(), 10, 10);
|
||||||
|
|
|
@ -21,8 +21,11 @@ package org.elasticsearch.client.documentation;
|
||||||
import org.elasticsearch.action.ActionListener;
|
import org.elasticsearch.action.ActionListener;
|
||||||
import org.elasticsearch.action.LatchedActionListener;
|
import org.elasticsearch.action.LatchedActionListener;
|
||||||
import org.elasticsearch.action.bulk.BulkRequest;
|
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.index.IndexRequest;
|
||||||
import org.elasticsearch.action.support.WriteRequest;
|
import org.elasticsearch.action.support.WriteRequest;
|
||||||
|
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
||||||
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
|
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
|
||||||
import org.elasticsearch.client.MachineLearningGetResultsIT;
|
import org.elasticsearch.client.MachineLearningGetResultsIT;
|
||||||
import org.elasticsearch.client.MachineLearningIT;
|
import org.elasticsearch.client.MachineLearningIT;
|
||||||
|
@ -31,6 +34,7 @@ import org.elasticsearch.client.RequestOptions;
|
||||||
import org.elasticsearch.client.RestHighLevelClient;
|
import org.elasticsearch.client.RestHighLevelClient;
|
||||||
import org.elasticsearch.client.ml.CloseJobRequest;
|
import org.elasticsearch.client.ml.CloseJobRequest;
|
||||||
import org.elasticsearch.client.ml.CloseJobResponse;
|
import org.elasticsearch.client.ml.CloseJobResponse;
|
||||||
|
import org.elasticsearch.client.ml.DeleteForecastRequest;
|
||||||
import org.elasticsearch.client.ml.DeleteJobRequest;
|
import org.elasticsearch.client.ml.DeleteJobRequest;
|
||||||
import org.elasticsearch.client.ml.DeleteJobResponse;
|
import org.elasticsearch.client.ml.DeleteJobResponse;
|
||||||
import org.elasticsearch.client.ml.FlushJobRequest;
|
import org.elasticsearch.client.ml.FlushJobRequest;
|
||||||
|
@ -639,8 +643,85 @@ public class MlClientDocumentationIT extends ESRestHighLevelClientTestCase {
|
||||||
assertTrue(latch.await(30L, TimeUnit.SECONDS));
|
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 {
|
public void testGetJobStats() throws Exception {
|
||||||
RestHighLevelClient client = highLevelClient();
|
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-update-job>>
|
||||||
* <<java-rest-high-x-pack-ml-get-job-stats>>
|
* <<java-rest-high-x-pack-ml-get-job-stats>>
|
||||||
* <<java-rest-high-x-pack-ml-forecast-job>>
|
* <<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-buckets>>
|
||||||
* <<java-rest-high-x-pack-ml-get-overall-buckets>>
|
* <<java-rest-high-x-pack-ml-get-overall-buckets>>
|
||||||
* <<java-rest-high-x-pack-ml-get-records>>
|
* <<java-rest-high-x-pack-ml-get-records>>
|
||||||
|
@ -237,6 +238,7 @@ include::ml/update-job.asciidoc[]
|
||||||
include::ml/flush-job.asciidoc[]
|
include::ml/flush-job.asciidoc[]
|
||||||
include::ml/get-job-stats.asciidoc[]
|
include::ml/get-job-stats.asciidoc[]
|
||||||
include::ml/forecast-job.asciidoc[]
|
include::ml/forecast-job.asciidoc[]
|
||||||
|
include::ml/delete-forecast.asciidoc[]
|
||||||
include::ml/get-buckets.asciidoc[]
|
include::ml/get-buckets.asciidoc[]
|
||||||
include::ml/get-overall-buckets.asciidoc[]
|
include::ml/get-overall-buckets.asciidoc[]
|
||||||
include::ml/get-records.asciidoc[]
|
include::ml/get-records.asciidoc[]
|
||||||
|
|
Loading…
Reference in New Issue