Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* 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.documentation;

import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.LatchedActionListener;
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.protocol.xpack.ml.PutJobRequest;
import org.elasticsearch.protocol.xpack.ml.PutJobResponse;
import org.elasticsearch.protocol.xpack.ml.job.config.AnalysisConfig;
import org.elasticsearch.protocol.xpack.ml.job.config.DataDescription;
import org.elasticsearch.protocol.xpack.ml.job.config.Detector;
import org.elasticsearch.protocol.xpack.ml.job.config.Job;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import static org.hamcrest.Matchers.greaterThan;

public class MlClientDocumentationIT extends ESRestHighLevelClientTestCase {

public void testCreateJob() throws Exception {
RestHighLevelClient client = highLevelClient();

//tag::x-pack-ml-put-job-detector
Detector.Builder detectorBuilder = new Detector.Builder()
.setFunction("sum") // <1>
.setFieldName("total") // <2>
.setDetectorDescription("Sum of total"); // <3>
//end::x-pack-ml-put-job-detector

//tag::x-pack-ml-put-job-analysis-config
List<Detector> detectors = Collections.singletonList(detectorBuilder.build()); // <1>
AnalysisConfig.Builder analysisConfigBuilder = new AnalysisConfig.Builder(detectors) // <2>
.setBucketSpan(TimeValue.timeValueMinutes(10)); // <3>
//end::x-pack-ml-put-job-analysis-config

//tag::x-pack-ml-put-job-data-description
DataDescription.Builder dataDescriptionBuilder = new DataDescription.Builder()
.setTimeField("timestamp"); // <1>
//end::x-pack-ml-put-job-data-description

{
String id = "job_1";

//tag::x-pack-ml-put-job-config
Job.Builder jobBuilder = new Job.Builder(id) // <1>
.setAnalysisConfig(analysisConfigBuilder) // <2>
.setDataDescription(dataDescriptionBuilder) // <3>
.setDescription("Total sum of requests"); // <4>
//end::x-pack-ml-put-job-config

//tag::x-pack-ml-put-job-request
PutJobRequest request = new PutJobRequest(jobBuilder.build()); // <1>
//end::x-pack-ml-put-job-request

//tag::x-pack-ml-put-job-execute
PutJobResponse response = client.machineLearning().putJob(request, RequestOptions.DEFAULT);
//end::x-pack-ml-put-job-execute

//tag::x-pack-ml-put-job-response
Date createTime = response.getResponse().getCreateTime(); // <1>
//end::x-pack-ml-put-job-response
assertThat(createTime.getTime(), greaterThan(0L));
}
{
String id = "job_2";
Job.Builder jobBuilder = new Job.Builder(id)
.setAnalysisConfig(analysisConfigBuilder)
.setDataDescription(dataDescriptionBuilder)
.setDescription("Total sum of requests");

PutJobRequest request = new PutJobRequest(jobBuilder.build());
// tag::x-pack-ml-put-job-execute-listener
ActionListener<PutJobResponse> listener = new ActionListener<PutJobResponse>() {
@Override
public void onResponse(PutJobResponse response) {
// <1>
}

@Override
public void onFailure(Exception e) {
// <2>
}
};
// end::x-pack-ml-put-job-execute-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-put-job-execute-async
client.machineLearning().putJobAsync(request, RequestOptions.DEFAULT, listener); // <1>
// end::x-pack-ml-put-job-execute-async

assertTrue(latch.await(30L, TimeUnit.SECONDS));
}
}
}
161 changes: 161 additions & 0 deletions docs/java-rest/high-level/ml/put_job.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
[[java-rest-high-x-pack-ml-put-job]]
=== Put Job API

The Put Job API can be used to create a new {ml} job
in the cluster. The API accepts a `PutJobRequest` object
as a request and returns a `PutJobResponse`.

[[java-rest-high-x-pack-ml-put-job-request]]
==== Put Job Request

A `PutJobRequest` requires the following argument:

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-put-job-request]
--------------------------------------------------
<1> The configuration of the {ml} job to create as a `Job`

[[java-rest-high-x-pack-ml-put-job-config]]
==== Job Configuration

The `Job` object contains all the details about the {ml} job
configuration.

A `Job` requires the following arguments:

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-put-job-config]
--------------------------------------------------
<1> The job ID
<2> An analysis configuration
<3> A data description
<4> Optionally, a human-readable description

[[java-rest-high-x-pack-ml-put-job-analysis-config]]
==== Analysis Configuration

The analysis configuration of the {ml} job is defined in the `AnalysisConfig`.
`AnalysisConfig` reflects all the configuration
settings that can be defined using the REST API.

Using the REST API, we could define this analysis configuration:

[source,js]
--------------------------------------------------
"analysis_config" : {
"bucket_span" : "10m",
"detectors" : [
{
"detector_description" : "Sum of total",
"function" : "sum",
"field_name" : "total"
}
]
}
--------------------------------------------------
// NOTCONSOLE

Using the `AnalysisConfig` object and the high level REST client, the list
of detectors must be built first.

An example of building a `Detector` instance is as follows:

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-put-job-detector]
--------------------------------------------------
<1> The function to use
<2> The field to apply the function to
<3> Optionally, a human-readable description

Then the same configuration would be:

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-put-job-analysis-config]
--------------------------------------------------
<1> Create a list of detectors
<2> Pass the list of detectors to the analysis config builder constructor
<3> The bucket span

[[java-rest-high-x-pack-ml-put-job-data-description]]
==== Data Description

After defining the analysis config, the next thing to define is the
data description, using a `DataDescription` instance. `DataDescription`
reflects all the configuration settings that can be defined using the
REST API.

Using the REST API, we could define this metrics configuration:

[source,js]
--------------------------------------------------
"data_description" : {
"time_field" : "timestamp"
}
--------------------------------------------------
// NOTCONSOLE

Using the `DataDescription` object and the high level REST client, the same
configuration would be:

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-put-job-data-description]
--------------------------------------------------
<1> The time field

[[java-rest-high-x-pack-ml-put-job-execution]]
==== Execution

The Put Job API can be executed through a `MachineLearningClient`
instance. Such an instance can be retrieved from a `RestHighLevelClient`
using the `machineLearning()` method:

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-put-job-execute]
--------------------------------------------------

[[java-rest-high-x-pack-ml-put-job-response]]
==== Response

The returned `PutJobResponse` returns the full representation of
the new {ml} job if it has been successfully created. This will
contain the creation time and other fields initialized using
default values:

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-put-job-response]
--------------------------------------------------
<1> The creation time is a field that was not passed in the `Job` object in the request

[[java-rest-high-x-pack-ml-put-job-async]]
==== Asynchronous Execution

This request can be executed asynchronously:

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-put-job-execute-async]
--------------------------------------------------
<1> The `PutMlJobRequest` 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 using the `onResponse` method
if the execution successfully completed or using the `onFailure` method if
it failed.

A typical listener for `PutJobResponse` looks like:

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-put-job-execute-listener]
--------------------------------------------------
<1> Called when the execution is successfully completed. The response is
provided as an argument
<2> Called in case of failure. The raised exception is provided as an argument
8 changes: 8 additions & 0 deletions docs/java-rest/high-level/supported-apis.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,14 @@ include::licensing/put-license.asciidoc[]
include::licensing/get-license.asciidoc[]
include::licensing/delete-license.asciidoc[]

== Machine Learning APIs

The Java High Level REST Client supports the following Machine Learning APIs:

* <<java-rest-high-x-pack-ml-put-job>>

include::ml/put_job.asciidoc[]

== Migration APIs

The Java High Level REST Client supports the following Migration APIs:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ public Builder(AnalysisConfig analysisConfig) {
this.multivariateByFields = analysisConfig.multivariateByFields;
}

public void setDetectors(List<Detector> detectors) {
public Builder setDetectors(List<Detector> detectors) {
Objects.requireNonNull(detectors, "[" + DETECTORS.getPreferredName() + "] must not be null");
// We always assign sequential IDs to the detectors that are correct for this analysis config
int detectorIndex = 0;
Expand All @@ -344,50 +344,62 @@ public void setDetectors(List<Detector> detectors) {
sequentialIndexDetectors.add(builder.build());
}
this.detectors = sequentialIndexDetectors;
return this;
}

public void setDetector(int detectorIndex, Detector detector) {
public Builder setDetector(int detectorIndex, Detector detector) {
detectors.set(detectorIndex, detector);
return this;
}

public void setBucketSpan(TimeValue bucketSpan) {
public Builder setBucketSpan(TimeValue bucketSpan) {
this.bucketSpan = bucketSpan;
return this;
}

public void setLatency(TimeValue latency) {
public Builder setLatency(TimeValue latency) {
this.latency = latency;
return this;
}

public void setCategorizationFieldName(String categorizationFieldName) {
public Builder setCategorizationFieldName(String categorizationFieldName) {
this.categorizationFieldName = categorizationFieldName;
return this;
}

public void setCategorizationFilters(List<String> categorizationFilters) {
public Builder setCategorizationFilters(List<String> categorizationFilters) {
this.categorizationFilters = categorizationFilters;
return this;
}

public void setCategorizationAnalyzerConfig(CategorizationAnalyzerConfig categorizationAnalyzerConfig) {
public Builder setCategorizationAnalyzerConfig(CategorizationAnalyzerConfig categorizationAnalyzerConfig) {
this.categorizationAnalyzerConfig = categorizationAnalyzerConfig;
return this;
}

public void setSummaryCountFieldName(String summaryCountFieldName) {
public Builder setSummaryCountFieldName(String summaryCountFieldName) {
this.summaryCountFieldName = summaryCountFieldName;
return this;
}

public void setInfluencers(List<String> influencers) {
public Builder setInfluencers(List<String> influencers) {
this.influencers = Objects.requireNonNull(influencers, INFLUENCERS.getPreferredName());
return this;
}

public void setOverlappingBuckets(Boolean overlappingBuckets) {
public Builder setOverlappingBuckets(Boolean overlappingBuckets) {
this.overlappingBuckets = overlappingBuckets;
return this;
}

public void setResultFinalizationWindow(Long resultFinalizationWindow) {
public Builder setResultFinalizationWindow(Long resultFinalizationWindow) {
this.resultFinalizationWindow = resultFinalizationWindow;
return this;
}

public void setMultivariateByFields(Boolean multivariateByFields) {
public Builder setMultivariateByFields(Boolean multivariateByFields) {
this.multivariateByFields = multivariateByFields;
return this;
}

public AnalysisConfig build() {
Expand Down
Loading