Skip to content

Commit db40315

Browse files
[HLRC][ML] Add ML get datafeed API to HLRC (#33715)
Relates #29827
1 parent 73417bf commit db40315

19 files changed

+736
-97
lines changed

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.elasticsearch.client.ml.ForecastJobRequest;
3636
import org.elasticsearch.client.ml.GetBucketsRequest;
3737
import org.elasticsearch.client.ml.GetCategoriesRequest;
38+
import org.elasticsearch.client.ml.GetDatafeedRequest;
3839
import org.elasticsearch.client.ml.GetInfluencersRequest;
3940
import org.elasticsearch.client.ml.GetJobRequest;
4041
import org.elasticsearch.client.ml.GetJobStatsRequest;
@@ -197,6 +198,24 @@ static Request putDatafeed(PutDatafeedRequest putDatafeedRequest) throws IOExcep
197198
return request;
198199
}
199200

201+
static Request getDatafeed(GetDatafeedRequest getDatafeedRequest) {
202+
String endpoint = new EndpointBuilder()
203+
.addPathPartAsIs("_xpack")
204+
.addPathPartAsIs("ml")
205+
.addPathPartAsIs("datafeeds")
206+
.addPathPart(Strings.collectionToCommaDelimitedString(getDatafeedRequest.getDatafeedIds()))
207+
.build();
208+
Request request = new Request(HttpGet.METHOD_NAME, endpoint);
209+
210+
RequestConverters.Params params = new RequestConverters.Params(request);
211+
if (getDatafeedRequest.isAllowNoDatafeeds() != null) {
212+
params.putParam(GetDatafeedRequest.ALLOW_NO_DATAFEEDS.getPreferredName(),
213+
Boolean.toString(getDatafeedRequest.isAllowNoDatafeeds()));
214+
}
215+
216+
return request;
217+
}
218+
200219
static Request deleteDatafeed(DeleteDatafeedRequest deleteDatafeedRequest) {
201220
String endpoint = new EndpointBuilder()
202221
.addPathPartAsIs("_xpack")

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

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
import org.elasticsearch.client.ml.GetBucketsResponse;
3434
import org.elasticsearch.client.ml.GetCategoriesRequest;
3535
import org.elasticsearch.client.ml.GetCategoriesResponse;
36+
import org.elasticsearch.client.ml.GetDatafeedRequest;
37+
import org.elasticsearch.client.ml.GetDatafeedResponse;
3638
import org.elasticsearch.client.ml.GetInfluencersRequest;
3739
import org.elasticsearch.client.ml.GetInfluencersResponse;
3840
import org.elasticsearch.client.ml.GetJobRequest;
@@ -466,8 +468,8 @@ public PutDatafeedResponse putDatafeed(PutDatafeedRequest request, RequestOption
466468
* For additional info
467469
* see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-put-datafeed.html">ML PUT datafeed documentation</a>
468470
*
469-
* @param request The request containing the {@link org.elasticsearch.client.ml.datafeed.DatafeedConfig} settings
470-
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
471+
* @param request The request containing the {@link org.elasticsearch.client.ml.datafeed.DatafeedConfig} settings
472+
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
471473
* @param listener Listener to be notified upon request completion
472474
*/
473475
public void putDatafeedAsync(PutDatafeedRequest request, RequestOptions options, ActionListener<PutDatafeedResponse> listener) {
@@ -479,6 +481,47 @@ public void putDatafeedAsync(PutDatafeedRequest request, RequestOptions options,
479481
Collections.emptySet());
480482
}
481483

484+
/**
485+
* Gets one or more Machine Learning datafeed configuration info.
486+
*
487+
* <p>
488+
* For additional info
489+
* see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-datafeed.html">ML GET datafeed documentation</a>
490+
*
491+
* @param request {@link GetDatafeedRequest} Request containing a list of datafeedId(s) and additional options
492+
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
493+
* @return {@link GetDatafeedResponse} response object containing
494+
* the {@link org.elasticsearch.client.ml.datafeed.DatafeedConfig} objects and the number of jobs found
495+
* @throws IOException when there is a serialization issue sending the request or receiving the response
496+
*/
497+
public GetDatafeedResponse getDatafeed(GetDatafeedRequest request, RequestOptions options) throws IOException {
498+
return restHighLevelClient.performRequestAndParseEntity(request,
499+
MLRequestConverters::getDatafeed,
500+
options,
501+
GetDatafeedResponse::fromXContent,
502+
Collections.emptySet());
503+
}
504+
505+
/**
506+
* Gets one or more Machine Learning datafeed configuration info, asynchronously.
507+
*
508+
* <p>
509+
* For additional info
510+
* see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-datafeed.html">ML GET datafeed documentation</a>
511+
*
512+
* @param request {@link GetDatafeedRequest} Request containing a list of datafeedId(s) and additional options
513+
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
514+
* @param listener Listener to be notified with {@link GetDatafeedResponse} upon request completion
515+
*/
516+
public void getDatafeedAsync(GetDatafeedRequest request, RequestOptions options, ActionListener<GetDatafeedResponse> listener) {
517+
restHighLevelClient.performRequestAsyncAndParseEntity(request,
518+
MLRequestConverters::getDatafeed,
519+
options,
520+
GetDatafeedResponse::fromXContent,
521+
listener,
522+
Collections.emptySet());
523+
}
524+
482525
/**
483526
* Deletes the given Machine Learning Datafeed
484527
* <p>

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ public Boolean isAllowNoJobs() {
136136
/**
137137
* Whether to ignore if a wildcard expression matches no jobs.
138138
*
139-
* This includes `_all` string or when no jobs have been specified
139+
* This includes {@code _all} string or when no jobs have been specified
140140
*
141-
* @param allowNoJobs When {@code true} ignore if wildcard or `_all` matches no jobs. Defaults to {@code true}
141+
* @param allowNoJobs When {@code true} ignore if wildcard or {@code _all} matches no jobs. Defaults to {@code true}
142142
*/
143143
public void setAllowNoJobs(boolean allowNoJobs) {
144144
this.allowNoJobs = allowNoJobs;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public Boolean isAllowNoForecasts() {
109109
}
110110

111111
/**
112-
* Sets the `allow_no_forecasts` field.
112+
* Sets the value of "allow_no_forecasts".
113113
*
114114
* @param allowNoForecasts when {@code true} no error is thrown when {@link DeleteForecastRequest#ALL} does not find any forecasts
115115
*/
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.elasticsearch.client.ml;
20+
21+
import org.elasticsearch.action.ActionRequest;
22+
import org.elasticsearch.action.ActionRequestValidationException;
23+
import org.elasticsearch.client.ml.datafeed.DatafeedConfig;
24+
import org.elasticsearch.common.ParseField;
25+
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
26+
import org.elasticsearch.common.xcontent.ToXContentObject;
27+
import org.elasticsearch.common.xcontent.XContentBuilder;
28+
29+
import java.io.IOException;
30+
import java.util.ArrayList;
31+
import java.util.Arrays;
32+
import java.util.List;
33+
import java.util.Objects;
34+
35+
/**
36+
* Request object to get {@link DatafeedConfig} objects with the matching {@code datafeedId}s.
37+
*
38+
* {@code _all} explicitly gets all the datafeeds in the cluster
39+
* An empty request (no {@code datafeedId}s) implicitly gets all the datafeeds in the cluster
40+
*/
41+
public class GetDatafeedRequest extends ActionRequest implements ToXContentObject {
42+
43+
public static final ParseField DATAFEED_IDS = new ParseField("datafeed_ids");
44+
public static final ParseField ALLOW_NO_DATAFEEDS = new ParseField("allow_no_datafeeds");
45+
46+
private static final String ALL_DATAFEEDS = "_all";
47+
private final List<String> datafeedIds;
48+
private Boolean allowNoDatafeeds;
49+
50+
@SuppressWarnings("unchecked")
51+
public static final ConstructingObjectParser<GetDatafeedRequest, Void> PARSER = new ConstructingObjectParser<>(
52+
"get_datafeed_request",
53+
true, a -> new GetDatafeedRequest(a[0] == null ? new ArrayList<>() : (List<String>) a[0]));
54+
55+
static {
56+
PARSER.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), DATAFEED_IDS);
57+
PARSER.declareBoolean(GetDatafeedRequest::setAllowNoDatafeeds, ALLOW_NO_DATAFEEDS);
58+
}
59+
60+
/**
61+
* Helper method to create a query that will get ALL datafeeds
62+
* @return new {@link GetDatafeedRequest} object searching for the datafeedId "_all"
63+
*/
64+
public static GetDatafeedRequest getAllDatafeedsRequest() {
65+
return new GetDatafeedRequest(ALL_DATAFEEDS);
66+
}
67+
68+
/**
69+
* Get the specified {@link DatafeedConfig} configurations via their unique datafeedIds
70+
* @param datafeedIds must not contain any null values
71+
*/
72+
public GetDatafeedRequest(String... datafeedIds) {
73+
this(Arrays.asList(datafeedIds));
74+
}
75+
76+
GetDatafeedRequest(List<String> datafeedIds) {
77+
if (datafeedIds.stream().anyMatch(Objects::isNull)) {
78+
throw new NullPointerException("datafeedIds must not contain null values");
79+
}
80+
this.datafeedIds = new ArrayList<>(datafeedIds);
81+
}
82+
83+
/**
84+
* All the datafeedIds for which to get configuration information
85+
*/
86+
public List<String> getDatafeedIds() {
87+
return datafeedIds;
88+
}
89+
90+
/**
91+
* Whether to ignore if a wildcard expression matches no datafeeds.
92+
*
93+
* @param allowNoDatafeeds If this is {@code false}, then an error is returned when a wildcard (or {@code _all})
94+
* does not match any datafeeds
95+
*/
96+
public void setAllowNoDatafeeds(boolean allowNoDatafeeds) {
97+
this.allowNoDatafeeds = allowNoDatafeeds;
98+
}
99+
100+
public Boolean isAllowNoDatafeeds() {
101+
return allowNoDatafeeds;
102+
}
103+
104+
@Override
105+
public ActionRequestValidationException validate() {
106+
return null;
107+
}
108+
109+
@Override
110+
public int hashCode() {
111+
return Objects.hash(datafeedIds, allowNoDatafeeds);
112+
}
113+
114+
@Override
115+
public boolean equals(Object other) {
116+
if (this == other) {
117+
return true;
118+
}
119+
120+
if (other == null || other.getClass() != getClass()) {
121+
return false;
122+
}
123+
124+
GetDatafeedRequest that = (GetDatafeedRequest) other;
125+
return Objects.equals(datafeedIds, that.datafeedIds) &&
126+
Objects.equals(allowNoDatafeeds, that.allowNoDatafeeds);
127+
}
128+
129+
@Override
130+
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
131+
builder.startObject();
132+
133+
if (datafeedIds.isEmpty() == false) {
134+
builder.field(DATAFEED_IDS.getPreferredName(), datafeedIds);
135+
}
136+
137+
if (allowNoDatafeeds != null) {
138+
builder.field(ALLOW_NO_DATAFEEDS.getPreferredName(), allowNoDatafeeds);
139+
}
140+
141+
builder.endObject();
142+
return builder;
143+
}
144+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.elasticsearch.client.ml;
20+
21+
import org.elasticsearch.client.ml.datafeed.DatafeedConfig;
22+
import org.elasticsearch.common.ParseField;
23+
import org.elasticsearch.common.Strings;
24+
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
25+
import org.elasticsearch.common.xcontent.XContentParser;
26+
27+
import java.io.IOException;
28+
import java.util.List;
29+
import java.util.Objects;
30+
import java.util.stream.Collectors;
31+
32+
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
33+
34+
/**
35+
* Contains a {@link List} of the found {@link DatafeedConfig} objects and the total count found
36+
*/
37+
public class GetDatafeedResponse extends AbstractResultResponse<DatafeedConfig> {
38+
39+
public static final ParseField RESULTS_FIELD = new ParseField("datafeeds");
40+
41+
@SuppressWarnings("unchecked")
42+
public static final ConstructingObjectParser<GetDatafeedResponse, Void> PARSER =
43+
new ConstructingObjectParser<>("get_datafeed_response", true,
44+
a -> new GetDatafeedResponse((List<DatafeedConfig.Builder>) a[0], (long) a[1]));
45+
46+
static {
47+
PARSER.declareObjectArray(constructorArg(), DatafeedConfig.PARSER, RESULTS_FIELD);
48+
PARSER.declareLong(constructorArg(), AbstractResultResponse.COUNT);
49+
}
50+
51+
GetDatafeedResponse(List<DatafeedConfig.Builder> datafeedBuilders, long count) {
52+
super(RESULTS_FIELD, datafeedBuilders.stream().map(DatafeedConfig.Builder::build).collect(Collectors.toList()), count);
53+
}
54+
55+
/**
56+
* The collection of {@link DatafeedConfig} objects found in the query
57+
*/
58+
public List<DatafeedConfig> datafeeds() {
59+
return results;
60+
}
61+
62+
public static GetDatafeedResponse fromXContent(XContentParser parser) throws IOException {
63+
return PARSER.parse(parser, null);
64+
}
65+
66+
@Override
67+
public int hashCode() {
68+
return Objects.hash(results, count);
69+
}
70+
71+
@Override
72+
public boolean equals(Object obj) {
73+
if (this == obj) {
74+
return true;
75+
}
76+
77+
if (obj == null || getClass() != obj.getClass()) {
78+
return false;
79+
}
80+
81+
GetDatafeedResponse other = (GetDatafeedResponse) obj;
82+
return Objects.equals(results, other.results) && count == other.count;
83+
}
84+
85+
@Override
86+
public final String toString() {
87+
return Strings.toString(this);
88+
}
89+
}

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@
3333
import java.util.Objects;
3434

3535
/**
36-
* Request object to get {@link Job} objects with the matching `jobId`s or
37-
* `groupName`s.
36+
* Request object to get {@link Job} objects with the matching {@code jobId}s or
37+
* {@code groupName}s.
3838
*
39-
* `_all` explicitly gets all the jobs in the cluster
40-
* An empty request (no `jobId`s) implicitly gets all the jobs in the cluster
39+
* {@code _all} explicitly gets all the jobs in the cluster
40+
* An empty request (no {@code jobId}s) implicitly gets all the jobs in the cluster
4141
*/
4242
public class GetJobRequest extends ActionRequest implements ToXContentObject {
4343

@@ -91,7 +91,7 @@ public List<String> getJobIds() {
9191
/**
9292
* Whether to ignore if a wildcard expression matches no jobs.
9393
*
94-
* @param allowNoJobs If this is {@code false}, then an error is returned when a wildcard (or `_all`) does not match any jobs
94+
* @param allowNoJobs If this is {@code false}, then an error is returned when a wildcard (or {@code _all}) does not match any jobs
9595
*/
9696
public void setAllowNoJobs(boolean allowNoJobs) {
9797
this.allowNoJobs = allowNoJobs;

0 commit comments

Comments
 (0)