[HLRC][ML] Add ML get datafeed API to HLRC (#33715)

Relates #29827
This commit is contained in:
Dimitris Athanasiou 2018-09-16 11:54:55 +01:00 committed by GitHub
parent 73417bf09a
commit db40315afb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 736 additions and 97 deletions

View File

@ -35,6 +35,7 @@ import org.elasticsearch.client.ml.FlushJobRequest;
import org.elasticsearch.client.ml.ForecastJobRequest;
import org.elasticsearch.client.ml.GetBucketsRequest;
import org.elasticsearch.client.ml.GetCategoriesRequest;
import org.elasticsearch.client.ml.GetDatafeedRequest;
import org.elasticsearch.client.ml.GetInfluencersRequest;
import org.elasticsearch.client.ml.GetJobRequest;
import org.elasticsearch.client.ml.GetJobStatsRequest;
@ -197,6 +198,24 @@ final class MLRequestConverters {
return request;
}
static Request getDatafeed(GetDatafeedRequest getDatafeedRequest) {
String endpoint = new EndpointBuilder()
.addPathPartAsIs("_xpack")
.addPathPartAsIs("ml")
.addPathPartAsIs("datafeeds")
.addPathPart(Strings.collectionToCommaDelimitedString(getDatafeedRequest.getDatafeedIds()))
.build();
Request request = new Request(HttpGet.METHOD_NAME, endpoint);
RequestConverters.Params params = new RequestConverters.Params(request);
if (getDatafeedRequest.isAllowNoDatafeeds() != null) {
params.putParam(GetDatafeedRequest.ALLOW_NO_DATAFEEDS.getPreferredName(),
Boolean.toString(getDatafeedRequest.isAllowNoDatafeeds()));
}
return request;
}
static Request deleteDatafeed(DeleteDatafeedRequest deleteDatafeedRequest) {
String endpoint = new EndpointBuilder()
.addPathPartAsIs("_xpack")

View File

@ -33,6 +33,8 @@ import org.elasticsearch.client.ml.GetBucketsRequest;
import org.elasticsearch.client.ml.GetBucketsResponse;
import org.elasticsearch.client.ml.GetCategoriesRequest;
import org.elasticsearch.client.ml.GetCategoriesResponse;
import org.elasticsearch.client.ml.GetDatafeedRequest;
import org.elasticsearch.client.ml.GetDatafeedResponse;
import org.elasticsearch.client.ml.GetInfluencersRequest;
import org.elasticsearch.client.ml.GetInfluencersResponse;
import org.elasticsearch.client.ml.GetJobRequest;
@ -479,6 +481,47 @@ public final class MachineLearningClient {
Collections.emptySet());
}
/**
* Gets one or more Machine Learning datafeed configuration info.
*
* <p>
* For additional info
* see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-datafeed.html">ML GET datafeed documentation</a>
*
* @param request {@link GetDatafeedRequest} Request containing a list of datafeedId(s) and additional options
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @return {@link GetDatafeedResponse} response object containing
* the {@link org.elasticsearch.client.ml.datafeed.DatafeedConfig} objects and the number of jobs found
* @throws IOException when there is a serialization issue sending the request or receiving the response
*/
public GetDatafeedResponse getDatafeed(GetDatafeedRequest request, RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(request,
MLRequestConverters::getDatafeed,
options,
GetDatafeedResponse::fromXContent,
Collections.emptySet());
}
/**
* Gets one or more Machine Learning datafeed configuration info, asynchronously.
*
* <p>
* For additional info
* see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-datafeed.html">ML GET datafeed documentation</a>
*
* @param request {@link GetDatafeedRequest} Request containing a list of datafeedId(s) and additional 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 with {@link GetDatafeedResponse} upon request completion
*/
public void getDatafeedAsync(GetDatafeedRequest request, RequestOptions options, ActionListener<GetDatafeedResponse> listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(request,
MLRequestConverters::getDatafeed,
options,
GetDatafeedResponse::fromXContent,
listener,
Collections.emptySet());
}
/**
* Deletes the given Machine Learning Datafeed
* <p>

View File

@ -136,9 +136,9 @@ public class CloseJobRequest extends ActionRequest implements ToXContentObject {
/**
* Whether to ignore if a wildcard expression matches no jobs.
*
* This includes `_all` string or when no jobs have been specified
* This includes {@code _all} string or when no jobs have been specified
*
* @param allowNoJobs When {@code true} ignore if wildcard or `_all` matches no jobs. Defaults to {@code true}
* @param allowNoJobs When {@code true} ignore if wildcard or {@code _all} matches no jobs. Defaults to {@code true}
*/
public void setAllowNoJobs(boolean allowNoJobs) {
this.allowNoJobs = allowNoJobs;

View File

@ -109,7 +109,7 @@ public class DeleteForecastRequest extends ActionRequest implements ToXContentOb
}
/**
* Sets the `allow_no_forecasts` field.
* Sets the value of "allow_no_forecasts".
*
* @param allowNoForecasts when {@code true} no error is thrown when {@link DeleteForecastRequest#ALL} does not find any forecasts
*/

View File

@ -0,0 +1,144 @@
/*
* 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.datafeed.DatafeedConfig;
import org.elasticsearch.common.ParseField;
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;
/**
* Request object to get {@link DatafeedConfig} objects with the matching {@code datafeedId}s.
*
* {@code _all} explicitly gets all the datafeeds in the cluster
* An empty request (no {@code datafeedId}s) implicitly gets all the datafeeds in the cluster
*/
public class GetDatafeedRequest extends ActionRequest implements ToXContentObject {
public static final ParseField DATAFEED_IDS = new ParseField("datafeed_ids");
public static final ParseField ALLOW_NO_DATAFEEDS = new ParseField("allow_no_datafeeds");
private static final String ALL_DATAFEEDS = "_all";
private final List<String> datafeedIds;
private Boolean allowNoDatafeeds;
@SuppressWarnings("unchecked")
public static final ConstructingObjectParser<GetDatafeedRequest, Void> PARSER = new ConstructingObjectParser<>(
"get_datafeed_request",
true, a -> new GetDatafeedRequest(a[0] == null ? new ArrayList<>() : (List<String>) a[0]));
static {
PARSER.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), DATAFEED_IDS);
PARSER.declareBoolean(GetDatafeedRequest::setAllowNoDatafeeds, ALLOW_NO_DATAFEEDS);
}
/**
* Helper method to create a query that will get ALL datafeeds
* @return new {@link GetDatafeedRequest} object searching for the datafeedId "_all"
*/
public static GetDatafeedRequest getAllDatafeedsRequest() {
return new GetDatafeedRequest(ALL_DATAFEEDS);
}
/**
* Get the specified {@link DatafeedConfig} configurations via their unique datafeedIds
* @param datafeedIds must not contain any null values
*/
public GetDatafeedRequest(String... datafeedIds) {
this(Arrays.asList(datafeedIds));
}
GetDatafeedRequest(List<String> datafeedIds) {
if (datafeedIds.stream().anyMatch(Objects::isNull)) {
throw new NullPointerException("datafeedIds must not contain null values");
}
this.datafeedIds = new ArrayList<>(datafeedIds);
}
/**
* All the datafeedIds for which to get configuration information
*/
public List<String> getDatafeedIds() {
return datafeedIds;
}
/**
* Whether to ignore if a wildcard expression matches no datafeeds.
*
* @param allowNoDatafeeds If this is {@code false}, then an error is returned when a wildcard (or {@code _all})
* does not match any datafeeds
*/
public void setAllowNoDatafeeds(boolean allowNoDatafeeds) {
this.allowNoDatafeeds = allowNoDatafeeds;
}
public Boolean isAllowNoDatafeeds() {
return allowNoDatafeeds;
}
@Override
public ActionRequestValidationException validate() {
return null;
}
@Override
public int hashCode() {
return Objects.hash(datafeedIds, allowNoDatafeeds);
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (other == null || other.getClass() != getClass()) {
return false;
}
GetDatafeedRequest that = (GetDatafeedRequest) other;
return Objects.equals(datafeedIds, that.datafeedIds) &&
Objects.equals(allowNoDatafeeds, that.allowNoDatafeeds);
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
if (datafeedIds.isEmpty() == false) {
builder.field(DATAFEED_IDS.getPreferredName(), datafeedIds);
}
if (allowNoDatafeeds != null) {
builder.field(ALLOW_NO_DATAFEEDS.getPreferredName(), allowNoDatafeeds);
}
builder.endObject();
return builder;
}
}

View File

@ -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.datafeed.DatafeedConfig;
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 DatafeedConfig} objects and the total count found
*/
public class GetDatafeedResponse extends AbstractResultResponse<DatafeedConfig> {
public static final ParseField RESULTS_FIELD = new ParseField("datafeeds");
@SuppressWarnings("unchecked")
public static final ConstructingObjectParser<GetDatafeedResponse, Void> PARSER =
new ConstructingObjectParser<>("get_datafeed_response", true,
a -> new GetDatafeedResponse((List<DatafeedConfig.Builder>) a[0], (long) a[1]));
static {
PARSER.declareObjectArray(constructorArg(), DatafeedConfig.PARSER, RESULTS_FIELD);
PARSER.declareLong(constructorArg(), AbstractResultResponse.COUNT);
}
GetDatafeedResponse(List<DatafeedConfig.Builder> datafeedBuilders, long count) {
super(RESULTS_FIELD, datafeedBuilders.stream().map(DatafeedConfig.Builder::build).collect(Collectors.toList()), count);
}
/**
* The collection of {@link DatafeedConfig} objects found in the query
*/
public List<DatafeedConfig> datafeeds() {
return results;
}
public static GetDatafeedResponse 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;
}
GetDatafeedResponse other = (GetDatafeedResponse) obj;
return Objects.equals(results, other.results) && count == other.count;
}
@Override
public final String toString() {
return Strings.toString(this);
}
}

View File

@ -33,11 +33,11 @@ import java.util.List;
import java.util.Objects;
/**
* Request object to get {@link Job} objects with the matching `jobId`s or
* `groupName`s.
* Request object to get {@link Job} objects with the matching {@code jobId}s or
* {@code groupName}s.
*
* `_all` explicitly gets all the jobs in the cluster
* An empty request (no `jobId`s) implicitly gets all the jobs in the cluster
* {@code _all} explicitly gets all the jobs in the cluster
* An empty request (no {@code jobId}s) implicitly gets all the jobs in the cluster
*/
public class GetJobRequest extends ActionRequest implements ToXContentObject {
@ -91,7 +91,7 @@ public class GetJobRequest extends ActionRequest implements ToXContentObject {
/**
* Whether to ignore if a wildcard expression matches no jobs.
*
* @param allowNoJobs If this is {@code false}, then an error is returned when a wildcard (or `_all`) does not match any jobs
* @param allowNoJobs If this is {@code false}, then an error is returned when a wildcard (or {@code _all}) does not match any jobs
*/
public void setAllowNoJobs(boolean allowNoJobs) {
this.allowNoJobs = allowNoJobs;

View File

@ -38,8 +38,8 @@ import java.util.Objects;
/**
* Request object to get {@link org.elasticsearch.client.ml.job.stats.JobStats} by their respective jobIds
*
* `_all` explicitly gets all the jobs' statistics in the cluster
* An empty request (no `jobId`s) implicitly gets all the jobs' statistics in the cluster
* {@code _all} explicitly gets all the jobs' statistics in the cluster
* An empty request (no {@code jobId}s) implicitly gets all the jobs' statistics in the cluster
*/
public class GetJobStatsRequest extends ActionRequest implements ToXContentObject {
@ -100,9 +100,9 @@ public class GetJobStatsRequest extends ActionRequest implements ToXContentObjec
/**
* Whether to ignore if a wildcard expression matches no jobs.
*
* This includes `_all` string or when no jobs have been specified
* This includes {@code _all} string or when no jobs have been specified
*
* @param allowNoJobs When {@code true} ignore if wildcard or `_all` matches no jobs. Defaults to {@code true}
* @param allowNoJobs When {@code true} ignore if wildcard or {@code _all} matches no jobs. Defaults to {@code true}
*/
public void setAllowNoJobs(boolean allowNoJobs) {
this.allowNoJobs = allowNoJobs;

View File

@ -109,7 +109,7 @@ public class GetOverallBucketsRequest extends ActionRequest implements ToXConten
}
/**
* Sets the value of `top_n`.
* Sets the value of "top_n".
* @param topN The number of top job bucket scores to be used in the overall_score calculation. Defaults to 1.
*/
public void setTopN(Integer topN) {
@ -121,7 +121,7 @@ public class GetOverallBucketsRequest extends ActionRequest implements ToXConten
}
/**
* Sets the value of `bucket_span`.
* Sets the value of "bucket_span".
* @param bucketSpan The span of the overall buckets. Must be greater or equal to the largest jobs bucket_span.
* Defaults to the largest jobs bucket_span.
*/
@ -197,7 +197,7 @@ public class GetOverallBucketsRequest extends ActionRequest implements ToXConten
/**
* Whether to ignore if a wildcard expression matches no jobs.
*
* If this is `false`, then an error is returned when a wildcard (or `_all`) does not match any jobs
* If this is {@code false}, then an error is returned when a wildcard (or {@code _all}) does not match any jobs
*/
public Boolean isAllowNoJobs() {
return allowNoJobs;

View File

@ -38,7 +38,7 @@ import java.util.Map;
import java.util.Objects;
/**
* POJO for posting data to a Machine Learning job
* Request to post data to a Machine Learning job
*/
public class PostDataRequest extends ActionRequest implements ToXContentObject {

View File

@ -31,6 +31,7 @@ import org.elasticsearch.client.ml.FlushJobRequest;
import org.elasticsearch.client.ml.ForecastJobRequest;
import org.elasticsearch.client.ml.GetBucketsRequest;
import org.elasticsearch.client.ml.GetCategoriesRequest;
import org.elasticsearch.client.ml.GetDatafeedRequest;
import org.elasticsearch.client.ml.GetInfluencersRequest;
import org.elasticsearch.client.ml.GetJobRequest;
import org.elasticsearch.client.ml.GetJobStatsRequest;
@ -227,6 +228,23 @@ public class MLRequestConvertersTests extends ESTestCase {
}
}
public void testGetDatafeed() {
GetDatafeedRequest getDatafeedRequest = new GetDatafeedRequest();
Request request = MLRequestConverters.getDatafeed(getDatafeedRequest);
assertEquals(HttpGet.METHOD_NAME, request.getMethod());
assertEquals("/_xpack/ml/datafeeds", request.getEndpoint());
assertFalse(request.getParameters().containsKey("allow_no_datafeeds"));
getDatafeedRequest = new GetDatafeedRequest("feed-1", "feed-*");
getDatafeedRequest.setAllowNoDatafeeds(true);
request = MLRequestConverters.getDatafeed(getDatafeedRequest);
assertEquals("/_xpack/ml/datafeeds/feed-1,feed-*", request.getEndpoint());
assertEquals(Boolean.toString(true), request.getParameters().get("allow_no_datafeeds"));
}
public void testDeleteDatafeed() {
String datafeedId = randomAlphaOfLength(10);
DeleteDatafeedRequest deleteDatafeedRequest = new DeleteDatafeedRequest(datafeedId);

View File

@ -32,6 +32,8 @@ import org.elasticsearch.client.ml.FlushJobRequest;
import org.elasticsearch.client.ml.FlushJobResponse;
import org.elasticsearch.client.ml.ForecastJobRequest;
import org.elasticsearch.client.ml.ForecastJobResponse;
import org.elasticsearch.client.ml.GetDatafeedRequest;
import org.elasticsearch.client.ml.GetDatafeedResponse;
import org.elasticsearch.client.ml.GetJobRequest;
import org.elasticsearch.client.ml.GetJobResponse;
import org.elasticsearch.client.ml.GetJobStatsRequest;
@ -58,6 +60,7 @@ import org.elasticsearch.client.ml.job.config.JobState;
import org.elasticsearch.client.ml.job.config.JobUpdate;
import org.elasticsearch.client.ml.job.stats.JobStats;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.rest.RestStatus;
import org.junit.After;
import java.io.IOException;
@ -316,6 +319,84 @@ public class MachineLearningIT extends ESRestHighLevelClientTestCase {
assertThat(createdDatafeed.getIndices(), equalTo(datafeedConfig.getIndices()));
}
public void testGetDatafeed() throws Exception {
String jobId1 = "test-get-datafeed-job-1";
String jobId2 = "test-get-datafeed-job-2";
Job job1 = buildJob(jobId1);
Job job2 = buildJob(jobId2);
MachineLearningClient machineLearningClient = highLevelClient().machineLearning();
machineLearningClient.putJob(new PutJobRequest(job1), RequestOptions.DEFAULT);
machineLearningClient.putJob(new PutJobRequest(job2), RequestOptions.DEFAULT);
String datafeedId1 = jobId1 + "-feed";
String datafeedId2 = jobId2 + "-feed";
DatafeedConfig datafeed1 = DatafeedConfig.builder(datafeedId1, jobId1).setIndices("data_1").build();
DatafeedConfig datafeed2 = DatafeedConfig.builder(datafeedId2, jobId2).setIndices("data_2").build();
machineLearningClient.putDatafeed(new PutDatafeedRequest(datafeed1), RequestOptions.DEFAULT);
machineLearningClient.putDatafeed(new PutDatafeedRequest(datafeed2), RequestOptions.DEFAULT);
// Test getting specific datafeeds
{
GetDatafeedRequest request = new GetDatafeedRequest(datafeedId1, datafeedId2);
GetDatafeedResponse response = execute(request, machineLearningClient::getDatafeed, machineLearningClient::getDatafeedAsync);
assertEquals(2, response.count());
assertThat(response.datafeeds(), hasSize(2));
assertThat(response.datafeeds().stream().map(DatafeedConfig::getId).collect(Collectors.toList()),
containsInAnyOrder(datafeedId1, datafeedId2));
}
// Test getting a single one
{
GetDatafeedRequest request = new GetDatafeedRequest(datafeedId1);
GetDatafeedResponse response = execute(request, machineLearningClient::getDatafeed, machineLearningClient::getDatafeedAsync);
assertTrue(response.count() == 1L);
assertThat(response.datafeeds().get(0).getId(), equalTo(datafeedId1));
}
// Test getting all datafeeds explicitly
{
GetDatafeedRequest request = GetDatafeedRequest.getAllDatafeedsRequest();
GetDatafeedResponse response = execute(request, machineLearningClient::getDatafeed, machineLearningClient::getDatafeedAsync);
assertTrue(response.count() == 2L);
assertTrue(response.datafeeds().size() == 2L);
assertThat(response.datafeeds().stream().map(DatafeedConfig::getId).collect(Collectors.toList()),
hasItems(datafeedId1, datafeedId2));
}
// Test getting all datafeeds implicitly
{
GetDatafeedResponse response = execute(new GetDatafeedRequest(), machineLearningClient::getDatafeed,
machineLearningClient::getDatafeedAsync);
assertTrue(response.count() >= 2L);
assertTrue(response.datafeeds().size() >= 2L);
assertThat(response.datafeeds().stream().map(DatafeedConfig::getId).collect(Collectors.toList()),
hasItems(datafeedId1, datafeedId2));
}
// Test get missing pattern with allow_no_datafeeds set to true
{
GetDatafeedRequest request = new GetDatafeedRequest("missing-*");
GetDatafeedResponse response = execute(request, machineLearningClient::getDatafeed, machineLearningClient::getDatafeedAsync);
assertThat(response.count(), equalTo(0L));
}
// Test get missing pattern with allow_no_datafeeds set to false
{
GetDatafeedRequest request = new GetDatafeedRequest("missing-*");
request.setAllowNoDatafeeds(false);
ElasticsearchStatusException e = expectThrows(ElasticsearchStatusException.class,
() -> execute(request, machineLearningClient::getDatafeed, machineLearningClient::getDatafeedAsync));
assertThat(e.status(), equalTo(RestStatus.NOT_FOUND));
}
}
public void testDeleteDatafeed() throws Exception {
String jobId = randomValidJobId();
Job job = buildJob(jobId);

View File

@ -45,6 +45,8 @@ import org.elasticsearch.client.ml.GetBucketsRequest;
import org.elasticsearch.client.ml.GetBucketsResponse;
import org.elasticsearch.client.ml.GetCategoriesRequest;
import org.elasticsearch.client.ml.GetCategoriesResponse;
import org.elasticsearch.client.ml.GetDatafeedRequest;
import org.elasticsearch.client.ml.GetDatafeedResponse;
import org.elasticsearch.client.ml.GetInfluencersRequest;
import org.elasticsearch.client.ml.GetInfluencersResponse;
import org.elasticsearch.client.ml.GetJobRequest;
@ -590,6 +592,59 @@ public class MlClientDocumentationIT extends ESRestHighLevelClientTestCase {
}
}
public void testGetDatafeed() throws Exception {
RestHighLevelClient client = highLevelClient();
Job job = MachineLearningIT.buildJob("get-datafeed-job");
client.machineLearning().putJob(new PutJobRequest(job), RequestOptions.DEFAULT);
String datafeedId = job.getId() + "-feed";
DatafeedConfig datafeed = DatafeedConfig.builder(datafeedId, job.getId()).setIndices("foo").build();
client.machineLearning().putDatafeed(new PutDatafeedRequest(datafeed), RequestOptions.DEFAULT);
{
//tag::x-pack-ml-get-datafeed-request
GetDatafeedRequest request = new GetDatafeedRequest(datafeedId); // <1>
request.setAllowNoDatafeeds(true); // <2>
//end::x-pack-ml-get-datafeed-request
//tag::x-pack-ml-get-datafeed-execute
GetDatafeedResponse response = client.machineLearning().getDatafeed(request, RequestOptions.DEFAULT);
long numberOfDatafeeds = response.count(); // <1>
List<DatafeedConfig> datafeeds = response.datafeeds(); // <2>
//end::x-pack-ml-get-datafeed-execute
assertEquals(1, numberOfDatafeeds);
assertEquals(1, datafeeds.size());
}
{
GetDatafeedRequest request = new GetDatafeedRequest(datafeedId);
// tag::x-pack-ml-get-datafeed-listener
ActionListener<GetDatafeedResponse> listener = new ActionListener<GetDatafeedResponse>() {
@Override
public void onResponse(GetDatafeedResponse response) {
// <1>
}
@Override
public void onFailure(Exception e) {
// <2>
}
};
// end::x-pack-ml-get-datafeed-listener
// 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-get-datafeed-execute-async
client.machineLearning().getDatafeedAsync(request, RequestOptions.DEFAULT, listener); // <1>
// end::x-pack-ml-get-datafeed-execute-async
assertTrue(latch.await(30L, TimeUnit.SECONDS));
}
}
public void testDeleteDatafeed() throws Exception {
RestHighLevelClient client = highLevelClient();

View File

@ -0,0 +1,70 @@
/*
* 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.datafeed.DatafeedConfigTests;
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 GetDatafeedRequestTests extends AbstractXContentTestCase<GetDatafeedRequest> {
public void testAllDatafeedRequest() {
GetDatafeedRequest request = GetDatafeedRequest.getAllDatafeedsRequest();
assertEquals(request.getDatafeedIds().size(), 1);
assertEquals(request.getDatafeedIds().get(0), "_all");
}
public void testNewWithDatafeedId() {
Exception exception = expectThrows(NullPointerException.class, () -> new GetDatafeedRequest("feed",null));
assertEquals(exception.getMessage(), "datafeedIds must not contain null values");
}
@Override
protected GetDatafeedRequest createTestInstance() {
int count = randomIntBetween(0, 10);
List<String> datafeedIds = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
datafeedIds.add(DatafeedConfigTests.randomValidDatafeedId());
}
GetDatafeedRequest request = new GetDatafeedRequest(datafeedIds);
if (randomBoolean()) {
request.setAllowNoDatafeeds(randomBoolean());
}
return request;
}
@Override
protected GetDatafeedRequest doParseInstance(XContentParser parser) throws IOException {
return GetDatafeedRequest.PARSER.parse(parser, null);
}
@Override
protected boolean supportsUnknownFields() {
return false;
}
}

View File

@ -0,0 +1,58 @@
/*
* 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.datafeed.DatafeedConfig;
import org.elasticsearch.client.ml.datafeed.DatafeedConfigTests;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractXContentTestCase;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class GetDatafeedResponseTests extends AbstractXContentTestCase<GetDatafeedResponse> {
@Override
protected GetDatafeedResponse createTestInstance() {
int count = randomIntBetween(1, 5);
List<DatafeedConfig.Builder> results = new ArrayList<>(count);
for(int i = 0; i < count; i++) {
DatafeedConfigTests.createRandomBuilder();
results.add(DatafeedConfigTests.createRandomBuilder());
}
return new GetDatafeedResponse(results, count);
}
@Override
protected GetDatafeedResponse doParseInstance(XContentParser parser) throws IOException {
return GetDatafeedResponse.fromXContent(parser);
}
@Override
protected Predicate<String> getRandomFieldsExcludeFilter() {
return field -> !field.isEmpty();
}
@Override
protected boolean supportsUnknownFields() {
return true;
}
}

View File

@ -64,6 +64,6 @@ public class GetJobRequestTests extends AbstractXContentTestCase<GetJobRequest>
@Override
protected boolean supportsUnknownFields() {
return true;
return false;
}
}

View File

@ -44,6 +44,10 @@ public class DatafeedConfigTests extends AbstractXContentTestCase<DatafeedConfig
}
public static DatafeedConfig createRandom() {
return createRandomBuilder().build();
}
public static DatafeedConfig.Builder createRandomBuilder() {
long bucketSpanMillis = 3600000;
DatafeedConfig.Builder builder = constructBuilder();
builder.setIndices(randomStringList(1, 10));
@ -99,7 +103,7 @@ public class DatafeedConfigTests extends AbstractXContentTestCase<DatafeedConfig
if (randomBoolean()) {
builder.setChunkingConfig(ChunkingConfigTests.createRandomizedChunk());
}
return builder.build();
return builder;
}
public static List<String> randomStringList(int min, int max) {

View File

@ -0,0 +1,56 @@
[[java-rest-high-x-pack-ml-get-datafeed]]
=== Get Datafeed API
The Get Datafeed API provides the ability to get {ml} datafeeds in the cluster.
It accepts a `GetDatafeedRequest` object and responds
with a `GetDatafeedResponse` object.
[[java-rest-high-x-pack-ml-get-datafeed-request]]
==== Get Datafeed Request
A `GetDatafeedRequest` object gets can have any number of `datafeedId` entries.
However, they all must be non-null. An empty list is the same as requesting for all datafeeds.
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-get-datafeed-request]
--------------------------------------------------
<1> Constructing a new request referencing existing `datafeedIds`, can contain wildcards
<2> Whether to ignore if a wildcard expression matches no datafeeds.
(This includes `_all` string or when no datafeeds have been specified)
[[java-rest-high-x-pack-ml-get-datafeed-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-get-datafeed-execute]
--------------------------------------------------
<1> The count of retrieved datafeeds
<2> The retrieved datafeeds
[[java-rest-high-x-pack-ml-get-datafeed-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-get-datafeed-execute-async]
--------------------------------------------------
<1> The `GetDatafeedRequest` 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 `GetDatafeedResponse` may
look like
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-get-datafeed-listener]
--------------------------------------------------
<1> `onResponse` is called back when the action is completed successfully
<2> `onFailure` is called back when some unexpected error occurs

View File

@ -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-put-datafeed>>
* <<java-rest-high-x-pack-ml-get-datafeed>>
* <<java-rest-high-x-pack-ml-delete-datafeed>>
* <<java-rest-high-x-pack-ml-forecast-job>>
* <<java-rest-high-x-pack-ml-delete-forecast>>
@ -240,6 +241,7 @@ include::ml/close-job.asciidoc[]
include::ml/update-job.asciidoc[]
include::ml/flush-job.asciidoc[]
include::ml/put-datafeed.asciidoc[]
include::ml/get-datafeed.asciidoc[]
include::ml/delete-datafeed.asciidoc[]
include::ml/get-job-stats.asciidoc[]
include::ml/forecast-job.asciidoc[]