HLRC: Get ML calendars (#33760)

This commit is contained in:
David Kyle 2018-09-18 11:51:11 +01:00 committed by GitHub
parent 2fa09f062e
commit 9543992d8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 563 additions and 66 deletions

View File

@ -34,6 +34,7 @@ import org.elasticsearch.client.ml.DeleteJobRequest;
import org.elasticsearch.client.ml.FlushJobRequest;
import org.elasticsearch.client.ml.ForecastJobRequest;
import org.elasticsearch.client.ml.GetBucketsRequest;
import org.elasticsearch.client.ml.GetCalendarsRequest;
import org.elasticsearch.client.ml.GetCategoriesRequest;
import org.elasticsearch.client.ml.GetDatafeedRequest;
import org.elasticsearch.client.ml.GetInfluencersRequest;
@ -229,7 +230,7 @@ final class MLRequestConverters {
return request;
}
static Request deleteForecast(DeleteForecastRequest deleteForecastRequest) throws IOException {
static Request deleteForecast(DeleteForecastRequest deleteForecastRequest) {
String endpoint = new EndpointBuilder()
.addPathPartAsIs("_xpack")
.addPathPartAsIs("ml")
@ -305,7 +306,7 @@ final class MLRequestConverters {
return request;
}
static Request postData(PostDataRequest postDataRequest) throws IOException {
static Request postData(PostDataRequest postDataRequest) {
String endpoint = new EndpointBuilder()
.addPathPartAsIs("_xpack")
.addPathPartAsIs("ml")
@ -359,4 +360,16 @@ final class MLRequestConverters {
request.setEntity(createEntity(putCalendarRequest, REQUEST_BODY_CONTENT_TYPE));
return request;
}
static Request getCalendars(GetCalendarsRequest getCalendarsRequest) throws IOException {
String endpoint = new EndpointBuilder()
.addPathPartAsIs("_xpack")
.addPathPartAsIs("ml")
.addPathPartAsIs("calendars")
.addPathPart(getCalendarsRequest.getCalendarId())
.build();
Request request = new Request(HttpGet.METHOD_NAME, endpoint);
request.setEntity(createEntity(getCalendarsRequest, REQUEST_BODY_CONTENT_TYPE));
return request;
}
}

View File

@ -31,6 +31,8 @@ import org.elasticsearch.client.ml.ForecastJobRequest;
import org.elasticsearch.client.ml.ForecastJobResponse;
import org.elasticsearch.client.ml.GetBucketsRequest;
import org.elasticsearch.client.ml.GetBucketsResponse;
import org.elasticsearch.client.ml.GetCalendarsRequest;
import org.elasticsearch.client.ml.GetCalendarsResponse;
import org.elasticsearch.client.ml.GetCategoriesRequest;
import org.elasticsearch.client.ml.GetCategoriesResponse;
import org.elasticsearch.client.ml.GetDatafeedRequest;
@ -792,6 +794,44 @@ public final class MachineLearningClient {
Collections.emptySet());
}
/**
* Gets a single or multiple calendars.
* <p>
* For additional info
* see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-calendar.html">ML GET calendars documentation</a>
*
* @param request The calendars request
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @return {@link GetCalendarsResponse} response object containing the {@link org.elasticsearch.client.ml.calendars.Calendar}
* objects and the number of calendars found
*/
public GetCalendarsResponse getCalendars(GetCalendarsRequest request, RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(request,
MLRequestConverters::getCalendars,
options,
GetCalendarsResponse::fromXContent,
Collections.emptySet());
}
/**
* Gets a single or multiple calendars, notifies listener once the requested records are retrieved.
* <p>
* For additional info
* see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-calendar.html">ML GET calendars documentation</a>
*
* @param request The calendars request
* @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 getCalendarsAsync(GetCalendarsRequest request, RequestOptions options, ActionListener<GetCalendarsResponse> listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(request,
MLRequestConverters::getCalendars,
options,
GetCalendarsResponse::fromXContent,
listener,
Collections.emptySet());
}
/**
* Gets the influencers for a Machine Learning Job.
* <p>

View File

@ -0,0 +1,104 @@
/*
* 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.calendars.Calendar;
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.client.ml.job.util.PageParams;
import java.io.IOException;
import java.util.Objects;
public class GetCalendarsRequest extends ActionRequest implements ToXContentObject {
public static final ObjectParser<GetCalendarsRequest, Void> PARSER =
new ObjectParser<>("get_calendars_request", GetCalendarsRequest::new);
static {
PARSER.declareString(GetCalendarsRequest::setCalendarId, Calendar.ID);
PARSER.declareObject(GetCalendarsRequest::setPageParams, PageParams.PARSER, PageParams.PAGE);
}
private String calendarId;
private PageParams pageParams;
public GetCalendarsRequest() {
}
public GetCalendarsRequest(String calendarId) {
this.calendarId = calendarId;
}
public String getCalendarId() {
return calendarId;
}
public void setCalendarId(String calendarId) {
this.calendarId = calendarId;
}
public PageParams getPageParams() {
return pageParams;
}
public void setPageParams(PageParams pageParams) {
this.pageParams = pageParams;
}
@Override
public ActionRequestValidationException validate() {
return null;
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
if (calendarId != null) {
builder.field(Calendar.ID.getPreferredName(), calendarId);
}
if (pageParams != null) {
builder.field(PageParams.PAGE.getPreferredName(), pageParams);
}
builder.endObject();
return builder;
}
@Override
public int hashCode() {
return Objects.hash(calendarId, pageParams);
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
GetCalendarsRequest other = (GetCalendarsRequest) obj;
return Objects.equals(calendarId, other.calendarId) && Objects.equals(pageParams, other.pageParams);
}
}

View File

@ -0,0 +1,86 @@
/*
* 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.calendars.Calendar;
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 static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
public class GetCalendarsResponse extends AbstractResultResponse<Calendar> {
public static final ParseField RESULTS_FIELD = new ParseField("calendars");
@SuppressWarnings("unchecked")
public static final ConstructingObjectParser<GetCalendarsResponse, Void> PARSER =
new ConstructingObjectParser<>("calendars_response", true,
a -> new GetCalendarsResponse((List<Calendar>) a[0], (long) a[1]));
static {
PARSER.declareObjectArray(constructorArg(), Calendar.PARSER, RESULTS_FIELD);
PARSER.declareLong(constructorArg(), AbstractResultResponse.COUNT);
}
public static GetCalendarsResponse fromXContent(XContentParser parser) throws IOException {
return PARSER.parse(parser, null);
}
GetCalendarsResponse(List<Calendar> calendars, long count) {
super(RESULTS_FIELD, calendars, count);
}
/**
* The collection of {@link Calendar} objects found in the query
*/
public List<Calendar> calendars() {
return results;
}
@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;
}
GetCalendarsResponse other = (GetCalendarsResponse) obj;
return Objects.equals(results, other.results) && count == other.count;
}
@Override
public final String toString() {
return Strings.toString(this);
}
}

View File

@ -19,16 +19,14 @@
package org.elasticsearch.client.ml.job.results;
import org.elasticsearch.client.ml.job.config.Job;
import org.elasticsearch.client.ml.job.util.TimeUtil;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.time.DateFormatters;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ObjectParser.ValueType;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser.Token;
import java.io.IOException;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@ -90,15 +88,9 @@ public class AnomalyRecord implements ToXContentObject {
static {
PARSER.declareString(ConstructingObjectParser.constructorArg(), Job.ID);
PARSER.declareField(ConstructingObjectParser.constructorArg(), p -> {
if (p.currentToken() == Token.VALUE_NUMBER) {
return new Date(p.longValue());
} else if (p.currentToken() == Token.VALUE_STRING) {
return new Date(DateFormatters.toZonedDateTime(DateTimeFormatter.ISO_INSTANT.parse(p.text())).toInstant().toEpochMilli());
}
throw new IllegalArgumentException("unexpected token [" + p.currentToken() + "] for ["
+ Result.TIMESTAMP.getPreferredName() + "]");
}, Result.TIMESTAMP, ValueType.VALUE);
PARSER.declareField(ConstructingObjectParser.constructorArg(),
(p) -> TimeUtil.parseTimeField(p, Result.TIMESTAMP.getPreferredName()),
Result.TIMESTAMP, ValueType.VALUE);
PARSER.declareLong(ConstructingObjectParser.constructorArg(), BUCKET_SPAN);
PARSER.declareString((anomalyRecord, s) -> {}, Result.RESULT_TYPE);
PARSER.declareDouble(AnomalyRecord::setProbability, PROBABILITY);

View File

@ -19,16 +19,14 @@
package org.elasticsearch.client.ml.job.results;
import org.elasticsearch.client.ml.job.config.Job;
import org.elasticsearch.client.ml.job.util.TimeUtil;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.time.DateFormatters;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ObjectParser.ValueType;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser.Token;
import java.io.IOException;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
@ -63,15 +61,8 @@ public class Bucket implements ToXContentObject {
static {
PARSER.declareString(ConstructingObjectParser.constructorArg(), Job.ID);
PARSER.declareField(ConstructingObjectParser.constructorArg(), p -> {
if (p.currentToken() == Token.VALUE_NUMBER) {
return new Date(p.longValue());
} else if (p.currentToken() == Token.VALUE_STRING) {
return new Date(DateFormatters.toZonedDateTime(DateTimeFormatter.ISO_INSTANT.parse(p.text())).toInstant().toEpochMilli());
}
throw new IllegalArgumentException("unexpected token [" + p.currentToken() + "] for ["
+ Result.TIMESTAMP.getPreferredName() + "]");
}, Result.TIMESTAMP, ValueType.VALUE);
PARSER.declareField(ConstructingObjectParser.constructorArg(),
(p) -> TimeUtil.parseTimeField(p, Result.TIMESTAMP.getPreferredName()), Result.TIMESTAMP, ValueType.VALUE);
PARSER.declareLong(ConstructingObjectParser.constructorArg(), BUCKET_SPAN);
PARSER.declareDouble(Bucket::setAnomalyScore, ANOMALY_SCORE);
PARSER.declareDouble(Bucket::setInitialAnomalyScore, INITIAL_ANOMALY_SCORE);

View File

@ -19,16 +19,14 @@
package org.elasticsearch.client.ml.job.results;
import org.elasticsearch.client.ml.job.config.Job;
import org.elasticsearch.client.ml.job.util.TimeUtil;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.time.DateFormatters;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ObjectParser.ValueType;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser.Token;
import java.io.IOException;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Objects;
@ -56,15 +54,9 @@ public class BucketInfluencer implements ToXContentObject {
static {
PARSER.declareString(ConstructingObjectParser.constructorArg(), Job.ID);
PARSER.declareField(ConstructingObjectParser.constructorArg(), p -> {
if (p.currentToken() == Token.VALUE_NUMBER) {
return new Date(p.longValue());
} else if (p.currentToken() == Token.VALUE_STRING) {
return new Date(DateFormatters.toZonedDateTime(DateTimeFormatter.ISO_INSTANT.parse(p.text())).toInstant().toEpochMilli());
}
throw new IllegalArgumentException("unexpected token [" + p.currentToken() + "] for ["
+ Result.TIMESTAMP.getPreferredName() + "]");
}, Result.TIMESTAMP, ValueType.VALUE);
PARSER.declareField(ConstructingObjectParser.constructorArg(),
(p) -> TimeUtil.parseTimeField(p, Result.TIMESTAMP.getPreferredName()),
Result.TIMESTAMP, ValueType.VALUE);
PARSER.declareLong(ConstructingObjectParser.constructorArg(), BUCKET_SPAN);
PARSER.declareString((bucketInfluencer, s) -> {}, Result.RESULT_TYPE);
PARSER.declareString(BucketInfluencer::setInfluencerFieldName, INFLUENCER_FIELD_NAME);

View File

@ -19,16 +19,14 @@
package org.elasticsearch.client.ml.job.results;
import org.elasticsearch.client.ml.job.config.Job;
import org.elasticsearch.client.ml.job.util.TimeUtil;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.time.DateFormatters;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ObjectParser.ValueType;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser.Token;
import java.io.IOException;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Objects;
@ -61,15 +59,9 @@ public class Influencer implements ToXContentObject {
PARSER.declareString(ConstructingObjectParser.constructorArg(), Job.ID);
PARSER.declareString(ConstructingObjectParser.constructorArg(), INFLUENCER_FIELD_NAME);
PARSER.declareString(ConstructingObjectParser.constructorArg(), INFLUENCER_FIELD_VALUE);
PARSER.declareField(ConstructingObjectParser.constructorArg(), p -> {
if (p.currentToken() == Token.VALUE_NUMBER) {
return new Date(p.longValue());
} else if (p.currentToken() == Token.VALUE_STRING) {
return new Date(DateFormatters.toZonedDateTime(DateTimeFormatter.ISO_INSTANT.parse(p.text())).toInstant().toEpochMilli());
}
throw new IllegalArgumentException("unexpected token [" + p.currentToken() + "] for ["
+ Result.TIMESTAMP.getPreferredName() + "]");
}, Result.TIMESTAMP, ValueType.VALUE);
PARSER.declareField(ConstructingObjectParser.constructorArg(),
(p) -> TimeUtil.parseTimeField(p, Result.TIMESTAMP.getPreferredName()),
Result.TIMESTAMP, ValueType.VALUE);
PARSER.declareLong(ConstructingObjectParser.constructorArg(), BUCKET_SPAN);
PARSER.declareString((influencer, s) -> {}, Result.RESULT_TYPE);
PARSER.declareDouble(Influencer::setProbability, PROBABILITY);

View File

@ -19,16 +19,14 @@
package org.elasticsearch.client.ml.job.results;
import org.elasticsearch.client.ml.job.config.Job;
import org.elasticsearch.client.ml.job.util.TimeUtil;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.time.DateFormatters;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@ -56,15 +54,9 @@ public class OverallBucket implements ToXContentObject {
a -> new OverallBucket((Date) a[0], (long) a[1], (double) a[2], (boolean) a[3]));
static {
PARSER.declareField(ConstructingObjectParser.constructorArg(), p -> {
if (p.currentToken() == XContentParser.Token.VALUE_NUMBER) {
return new Date(p.longValue());
} else if (p.currentToken() == XContentParser.Token.VALUE_STRING) {
return new Date(DateFormatters.toZonedDateTime(DateTimeFormatter.ISO_INSTANT.parse(p.text())).toInstant().toEpochMilli());
}
throw new IllegalArgumentException("unexpected token [" + p.currentToken() + "] for ["
+ Result.TIMESTAMP.getPreferredName() + "]");
}, Result.TIMESTAMP, ObjectParser.ValueType.VALUE);
PARSER.declareField(ConstructingObjectParser.constructorArg(),
(p) -> TimeUtil.parseTimeField(p, Result.TIMESTAMP.getPreferredName()),
Result.TIMESTAMP, ObjectParser.ValueType.VALUE);
PARSER.declareLong(ConstructingObjectParser.constructorArg(), BUCKET_SPAN);
PARSER.declareDouble(ConstructingObjectParser.constructorArg(), OVERALL_SCORE);
PARSER.declareBoolean(ConstructingObjectParser.constructorArg(), Result.IS_INTERIM);

View File

@ -28,7 +28,6 @@ public final class Result {
/**
* Serialisation fields
*/
public static final ParseField TYPE = new ParseField("result");
public static final ParseField RESULT_TYPE = new ParseField("result_type");
public static final ParseField TIMESTAMP = new ParseField("timestamp");
public static final ParseField IS_INTERIM = new ParseField("is_interim");

View File

@ -30,6 +30,7 @@ import org.elasticsearch.client.ml.DeleteJobRequest;
import org.elasticsearch.client.ml.FlushJobRequest;
import org.elasticsearch.client.ml.ForecastJobRequest;
import org.elasticsearch.client.ml.GetBucketsRequest;
import org.elasticsearch.client.ml.GetCalendarsRequest;
import org.elasticsearch.client.ml.GetCategoriesRequest;
import org.elasticsearch.client.ml.GetDatafeedRequest;
import org.elasticsearch.client.ml.GetInfluencersRequest;
@ -259,7 +260,7 @@ public class MLRequestConvertersTests extends ESTestCase {
assertEquals(Boolean.toString(true), request.getParameters().get("force"));
}
public void testDeleteForecast() throws Exception {
public void testDeleteForecast() {
String jobId = randomAlphaOfLength(10);
DeleteForecastRequest deleteForecastRequest = new DeleteForecastRequest(jobId);
@ -415,6 +416,28 @@ public class MLRequestConvertersTests extends ESTestCase {
}
}
public void testGetCalendars() throws IOException {
GetCalendarsRequest getCalendarsRequest = new GetCalendarsRequest();
String expectedEndpoint = "/_xpack/ml/calendars";
if (randomBoolean()) {
String calendarId = randomAlphaOfLength(10);
getCalendarsRequest.setCalendarId(calendarId);
expectedEndpoint += "/" + calendarId;
}
if (randomBoolean()) {
getCalendarsRequest.setPageParams(new PageParams(10, 20));
}
Request request = MLRequestConverters.getCalendars(getCalendarsRequest);
assertEquals(HttpGet.METHOD_NAME, request.getMethod());
assertEquals(expectedEndpoint, request.getEndpoint());
try (XContentParser parser = createParser(JsonXContent.jsonXContent, request.getEntity().getContent())) {
GetCalendarsRequest parsedRequest = GetCalendarsRequest.PARSER.apply(parser, null);
assertThat(parsedRequest, equalTo(getCalendarsRequest));
}
}
private static Job createValidJob(String jobId) {
AnalysisConfig.Builder analysisConfig = AnalysisConfig.builder(Collections.singletonList(
Detector.builder().setFunction("count").build()));

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.GetCalendarsRequest;
import org.elasticsearch.client.ml.GetCalendarsResponse;
import org.elasticsearch.client.ml.GetDatafeedRequest;
import org.elasticsearch.client.ml.GetDatafeedResponse;
import org.elasticsearch.client.ml.GetJobRequest;
@ -483,7 +485,6 @@ public class MachineLearningIT extends ESRestHighLevelClientTestCase {
}
public void testPutCalendar() throws IOException {
Calendar calendar = CalendarTests.testInstance();
MachineLearningClient machineLearningClient = highLevelClient().machineLearning();
PutCalendarResponse putCalendarResponse = execute(new PutCalendarRequest(calendar), machineLearningClient::putCalendar,
@ -492,6 +493,30 @@ public class MachineLearningIT extends ESRestHighLevelClientTestCase {
assertThat(putCalendarResponse.getCalendar(), equalTo(calendar));
}
public void testGetCalendars() throws Exception {
Calendar calendar1 = CalendarTests.testInstance();
Calendar calendar2 = CalendarTests.testInstance();
MachineLearningClient machineLearningClient = highLevelClient().machineLearning();
machineLearningClient.putCalendar(new PutCalendarRequest(calendar1), RequestOptions.DEFAULT);
machineLearningClient.putCalendar(new PutCalendarRequest(calendar2), RequestOptions.DEFAULT);
GetCalendarsRequest getCalendarsRequest = new GetCalendarsRequest();
getCalendarsRequest.setCalendarId("_all");
GetCalendarsResponse getCalendarsResponse = execute(getCalendarsRequest, machineLearningClient::getCalendars,
machineLearningClient::getCalendarsAsync);
assertEquals(2, getCalendarsResponse.count());
assertEquals(2, getCalendarsResponse.calendars().size());
assertThat(getCalendarsResponse.calendars().stream().map(Calendar::getId).collect(Collectors.toList()),
hasItems(calendar1.getId(), calendar1.getId()));
getCalendarsRequest.setCalendarId(calendar1.getId());
getCalendarsResponse = execute(getCalendarsRequest, machineLearningClient::getCalendars,
machineLearningClient::getCalendarsAsync);
assertEquals(1, getCalendarsResponse.count());
assertEquals(calendar1, getCalendarsResponse.calendars().get(0));
}
public static String randomValidJobId() {
CodepointSetGenerator generator = new CodepointSetGenerator("abcdefghijklmnopqrstuvwxyz0123456789".toCharArray());
return generator.ofCodePointsLength(random(), 10, 10);

View File

@ -43,6 +43,8 @@ import org.elasticsearch.client.ml.ForecastJobRequest;
import org.elasticsearch.client.ml.ForecastJobResponse;
import org.elasticsearch.client.ml.GetBucketsRequest;
import org.elasticsearch.client.ml.GetBucketsResponse;
import org.elasticsearch.client.ml.GetCalendarsRequest;
import org.elasticsearch.client.ml.GetCalendarsResponse;
import org.elasticsearch.client.ml.GetCategoriesRequest;
import org.elasticsearch.client.ml.GetCategoriesResponse;
import org.elasticsearch.client.ml.GetDatafeedRequest;
@ -880,6 +882,7 @@ public class MlClientDocumentationIT extends ESRestHighLevelClientTestCase {
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();
@ -1526,4 +1529,66 @@ public class MlClientDocumentationIT extends ESRestHighLevelClientTestCase {
assertTrue(latch.await(30L, TimeUnit.SECONDS));
}
public void testGetCalendar() throws IOException, InterruptedException {
RestHighLevelClient client = highLevelClient();
Calendar calendar = new Calendar("holidays", Collections.singletonList("job_1"), "A calendar for public holidays");
PutCalendarRequest putRequest = new PutCalendarRequest(calendar);
client.machineLearning().putCalendar(putRequest, RequestOptions.DEFAULT);
{
//tag::x-pack-ml-get-calendars-request
GetCalendarsRequest request = new GetCalendarsRequest(); // <1>
//end::x-pack-ml-get-calendars-request
//tag::x-pack-ml-get-calendars-id
request.setCalendarId("holidays"); // <1>
//end::x-pack-ml-get-calendars-id
//tag::x-pack-ml-get-calendars-page
request.setPageParams(new PageParams(10, 20)); // <1>
//end::x-pack-ml-get-calendars-page
// reset page params
request.setPageParams(null);
//tag::x-pack-ml-get-calendars-execution
GetCalendarsResponse response = client.machineLearning().getCalendars(request, RequestOptions.DEFAULT);
//end::x-pack-ml-get-calendars-execution
// tag::x-pack-ml-get-calendars-response
long count = response.count(); // <1>
List<Calendar> calendars = response.calendars(); // <2>
// end::x-pack-ml-get-calendars-response
assertEquals(1, calendars.size());
}
{
GetCalendarsRequest request = new GetCalendarsRequest("holidays");
// tag::x-pack-ml-get-calendars-listener
ActionListener<GetCalendarsResponse> listener =
new ActionListener<GetCalendarsResponse>() {
@Override
public void onResponse(GetCalendarsResponse getCalendarsResponse) {
// <1>
}
@Override
public void onFailure(Exception e) {
// <2>
}
};
// end::x-pack-ml-get-calendars-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-calendars-execute-async
client.machineLearning().getCalendarsAsync(request, RequestOptions.DEFAULT, listener); // <1>
// end::x-pack-ml-get-calendars-execute-async
assertTrue(latch.await(30L, TimeUnit.SECONDS));
}
}
}

View File

@ -0,0 +1,46 @@
/*
* 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.util.PageParams;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractXContentTestCase;
public class GetCalendarsRequestTests extends AbstractXContentTestCase<GetCalendarsRequest> {
@Override
protected GetCalendarsRequest createTestInstance() {
GetCalendarsRequest request = new GetCalendarsRequest();
request.setCalendarId(randomAlphaOfLength(9));
if (randomBoolean()) {
request.setPageParams(new PageParams(1, 2));
}
return request;
}
@Override
protected GetCalendarsRequest doParseInstance(XContentParser parser) {
return GetCalendarsRequest.PARSER.apply(parser, null);
}
@Override
protected boolean supportsUnknownFields() {
return false;
}
}

View File

@ -0,0 +1,52 @@
/*
* 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.calendars.Calendar;
import org.elasticsearch.client.ml.calendars.CalendarTests;
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 GetCalendarsResponseTests extends AbstractXContentTestCase<GetCalendarsResponse> {
@Override
protected GetCalendarsResponse createTestInstance() {
List<Calendar> calendars = new ArrayList<>();
int count = randomIntBetween(0, 3);
for (int i=0; i<count; i++) {
calendars.add(CalendarTests.testInstance());
}
return new GetCalendarsResponse(calendars, count);
}
@Override
protected GetCalendarsResponse doParseInstance(XContentParser parser) throws IOException {
return GetCalendarsResponse.fromXContent(parser);
}
@Override
protected boolean supportsUnknownFields() {
return true;
}
}

View File

@ -0,0 +1,83 @@
[[java-rest-high-x-pack-ml-get-calendars]]
=== Get Calendars API
Retrieves one or more calendar objects.
It accepts a `GetCalendarsRequest` and responds
with a `GetCalendarsResponse` object.
[[java-rest-high-x-pack-ml-get-calendars-request]]
==== Get Calendars Request
By default a `GetCalendarsRequest` with no calendar Id set will return all
calendars. Using the literal `_all` also returns all calendars.
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-get-calendars-request]
--------------------------------------------------
<1> Constructing a new request for all calendars
==== Optional Arguments
The following arguments are optional:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-get-calendars-id]
--------------------------------------------------
<1> Construct a request for the single calendar `holidays`
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-get-calendars-page]
--------------------------------------------------
<1> The page parameters `from` and `size`. `from` specifies the number of calendars to skip.
`size` specifies the maximum number of calendars to get. Defaults to `0` and `100` respectively.
[[java-rest-high-x-pack-ml-get-calendars-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-calendars-execution]
--------------------------------------------------
[[java-rest-high-x-pack-ml-get-calendars-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-calendars-execute-async]
--------------------------------------------------
<1> The `GetCalendarsRequest` to execute and the `ActionListener` to use when
the execution completes
The asynchronous method does not block and returns immediately. Once it is
completed the `ActionListener` is called back with the `onResponse` method
if the execution is successful or the `onFailure` method if the execution
failed.
A typical listener for `GetCalendarsResponse` looks like:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-get-calendars-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-get-calendars-response]]
==== Get calendars Response
The returned `GetCalendarsResponse` contains the requested calendars:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-get-calendars-response]
--------------------------------------------------
<1> The count of calendars that were matched
<2> The calendars retrieved

View File

@ -4,7 +4,7 @@ Creates a new {ml} calendar.
The API accepts a `PutCalendarRequest` and responds
with a `PutCalendarResponse` object.
[[java-rest-high-x-pack-ml-get-calendars-request]]
[[java-rest-high-x-pack-ml-put-calendar-request]]
==== Put Calendar Request
A `PutCalendarRequest` is constructed with a Calendar object

View File

@ -231,6 +231,7 @@ The Java High Level REST Client supports the following Machine Learning APIs:
* <<java-rest-high-x-pack-ml-post-data>>
* <<java-rest-high-x-pack-ml-get-influencers>>
* <<java-rest-high-x-pack-ml-get-categories>>
* <<java-rest-high-x-pack-ml-get-calendars>>
* <<java-rest-high-x-pack-ml-put-calendar>>
include::ml/put-job.asciidoc[]
@ -252,6 +253,7 @@ include::ml/get-records.asciidoc[]
include::ml/post-data.asciidoc[]
include::ml/get-influencers.asciidoc[]
include::ml/get-categories.asciidoc[]
include::ml/get-calendars.asciidoc[]
include::ml/put-calendar.asciidoc[]
== Migration APIs