Skip to content

Commit b824ed9

Browse files
[HLRC][ML] Add ML get datafeed API to HLRC (#33715)
Relates #29827
1 parent 2ae3b44 commit b824ed9

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;
@@ -196,6 +197,24 @@ static Request putDatafeed(PutDatafeedRequest putDatafeedRequest) throws IOExcep
196197
return request;
197198
}
198199

200+
static Request getDatafeed(GetDatafeedRequest getDatafeedRequest) {
201+
String endpoint = new EndpointBuilder()
202+
.addPathPartAsIs("_xpack")
203+
.addPathPartAsIs("ml")
204+
.addPathPartAsIs("datafeeds")
205+
.addPathPart(Strings.collectionToCommaDelimitedString(getDatafeedRequest.getDatafeedIds()))
206+
.build();
207+
Request request = new Request(HttpGet.METHOD_NAME, endpoint);
208+
209+
RequestConverters.Params params = new RequestConverters.Params(request);
210+
if (getDatafeedRequest.isAllowNoDatafeeds() != null) {
211+
params.putParam(GetDatafeedRequest.ALLOW_NO_DATAFEEDS.getPreferredName(),
212+
Boolean.toString(getDatafeedRequest.isAllowNoDatafeeds()));
213+
}
214+
215+
return request;
216+
}
217+
199218
static Request deleteDatafeed(DeleteDatafeedRequest deleteDatafeedRequest) {
200219
String endpoint = new EndpointBuilder()
201220
.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;
@@ -479,8 +481,8 @@ public PutDatafeedResponse putDatafeed(PutDatafeedRequest request, RequestOption
479481
* For additional info
480482
* see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-put-datafeed.html">ML PUT datafeed documentation</a>
481483
*
482-
* @param request The request containing the {@link org.elasticsearch.client.ml.datafeed.DatafeedConfig} settings
483-
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
484+
* @param request The request containing the {@link org.elasticsearch.client.ml.datafeed.DatafeedConfig} settings
485+
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
484486
* @param listener Listener to be notified upon request completion
485487
*/
486488
public void putDatafeedAsync(PutDatafeedRequest request, RequestOptions options, ActionListener<PutDatafeedResponse> listener) {
@@ -492,6 +494,47 @@ public void putDatafeedAsync(PutDatafeedRequest request, RequestOptions options,
492494
Collections.emptySet());
493495
}
494496

497+
/**
498+
* Gets one or more Machine Learning datafeed configuration info.
499+
*
500+
* <p>
501+
* For additional info
502+
* see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-datafeed.html">ML GET datafeed documentation</a>
503+
*
504+
* @param request {@link GetDatafeedRequest} Request containing a list of datafeedId(s) and additional options
505+
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
506+
* @return {@link GetDatafeedResponse} response object containing
507+
* the {@link org.elasticsearch.client.ml.datafeed.DatafeedConfig} objects and the number of jobs found
508+
* @throws IOException when there is a serialization issue sending the request or receiving the response
509+
*/
510+
public GetDatafeedResponse getDatafeed(GetDatafeedRequest request, RequestOptions options) throws IOException {
511+
return restHighLevelClient.performRequestAndParseEntity(request,
512+
MLRequestConverters::getDatafeed,
513+
options,
514+
GetDatafeedResponse::fromXContent,
515+
Collections.emptySet());
516+
}
517+
518+
/**
519+
* Gets one or more Machine Learning datafeed configuration info, asynchronously.
520+
*
521+
* <p>
522+
* For additional info
523+
* see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-datafeed.html">ML GET datafeed documentation</a>
524+
*
525+
* @param request {@link GetDatafeedRequest} Request containing a list of datafeedId(s) and additional options
526+
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
527+
* @param listener Listener to be notified with {@link GetDatafeedResponse} upon request completion
528+
*/
529+
public void getDatafeedAsync(GetDatafeedRequest request, RequestOptions options, ActionListener<GetDatafeedResponse> listener) {
530+
restHighLevelClient.performRequestAsyncAndParseEntity(request,
531+
MLRequestConverters::getDatafeed,
532+
options,
533+
GetDatafeedResponse::fromXContent,
534+
listener,
535+
Collections.emptySet());
536+
}
537+
495538
/**
496539
* Deletes the given Machine Learning Datafeed
497540
* <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)