[ML] Fix filter influencers by score

Add more test coverage

Original commit: elastic/x-pack-elasticsearch@45b06d2a5b
This commit is contained in:
David Kyle 2017-04-24 11:26:40 +01:00
parent 5dc8c71e65
commit 2c6a4d8627
8 changed files with 108 additions and 52 deletions

View File

@ -66,7 +66,7 @@ extends Action<GetInfluencersAction.Request, GetInfluencersAction.Response, GetI
public static final ParseField START = new ParseField("start");
public static final ParseField END = new ParseField("end");
public static final ParseField EXCLUDE_INTERIM = new ParseField("exclude_interim");
public static final ParseField ANOMALY_SCORE = new ParseField("anomaly_score");
public static final ParseField INFLUENCER_SCORE = new ParseField("influencer_score");
public static final ParseField SORT_FIELD = new ParseField("sort");
public static final ParseField DESCENDING_SORT = new ParseField("desc");
@ -78,7 +78,7 @@ extends Action<GetInfluencersAction.Request, GetInfluencersAction.Response, GetI
PARSER.declareStringOrNull(Request::setEnd, END);
PARSER.declareBoolean(Request::setExcludeInterim, EXCLUDE_INTERIM);
PARSER.declareObject(Request::setPageParams, PageParams.PARSER, PageParams.PAGE);
PARSER.declareDouble(Request::setAnomalyScore, ANOMALY_SCORE);
PARSER.declareDouble(Request::setInfluencerScore, INFLUENCER_SCORE);
PARSER.declareString(Request::setSort, SORT_FIELD);
PARSER.declareBoolean(Request::setDescending, DESCENDING_SORT);
}
@ -96,7 +96,7 @@ extends Action<GetInfluencersAction.Request, GetInfluencersAction.Response, GetI
private String end;
private boolean excludeInterim = false;
private PageParams pageParams = new PageParams();
private double anomalyScoreFilter = 0.0;
private double influencerScore = 0.0;
private String sort = Influencer.INFLUENCER_SCORE.getPreferredName();
private boolean descending = false;
@ -151,12 +151,12 @@ extends Action<GetInfluencersAction.Request, GetInfluencersAction.Response, GetI
return pageParams;
}
public double getAnomalyScoreFilter() {
return anomalyScoreFilter;
public double getInfluencerScore() {
return influencerScore;
}
public void setAnomalyScore(double anomalyScoreFilter) {
this.anomalyScoreFilter = anomalyScoreFilter;
public void setInfluencerScore(double anomalyScoreFilter) {
this.influencerScore = anomalyScoreFilter;
}
public String getSort() {
@ -182,7 +182,7 @@ extends Action<GetInfluencersAction.Request, GetInfluencersAction.Response, GetI
end = in.readOptionalString();
sort = in.readOptionalString();
descending = in.readBoolean();
anomalyScoreFilter = in.readDouble();
influencerScore = in.readDouble();
}
@Override
@ -195,7 +195,7 @@ extends Action<GetInfluencersAction.Request, GetInfluencersAction.Response, GetI
out.writeOptionalString(end);
out.writeOptionalString(sort);
out.writeBoolean(descending);
out.writeDouble(anomalyScoreFilter);
out.writeDouble(influencerScore);
}
@Override
@ -208,14 +208,14 @@ extends Action<GetInfluencersAction.Request, GetInfluencersAction.Response, GetI
builder.field(END.getPreferredName(), end);
builder.field(SORT_FIELD.getPreferredName(), sort);
builder.field(DESCENDING_SORT.getPreferredName(), descending);
builder.field(ANOMALY_SCORE.getPreferredName(), anomalyScoreFilter);
builder.field(INFLUENCER_SCORE.getPreferredName(), influencerScore);
builder.endObject();
return builder;
}
@Override
public int hashCode() {
return Objects.hash(jobId, excludeInterim, pageParams, start, end, sort, descending, anomalyScoreFilter);
return Objects.hash(jobId, excludeInterim, pageParams, start, end, sort, descending, influencerScore);
}
@Override
@ -231,7 +231,7 @@ extends Action<GetInfluencersAction.Request, GetInfluencersAction.Response, GetI
&& Objects.equals(end, other.end)
&& Objects.equals(excludeInterim, other.excludeInterim)
&& Objects.equals(pageParams, other.pageParams)
&& Objects.equals(anomalyScoreFilter, other.anomalyScoreFilter)
&& Objects.equals(influencerScore, other.influencerScore)
&& Objects.equals(descending, other.descending)
&& Objects.equals(sort, other.sort);
}
@ -323,7 +323,7 @@ extends Action<GetInfluencersAction.Request, GetInfluencersAction.Response, GetI
InfluencersQueryBuilder.InfluencersQuery query = new InfluencersQueryBuilder().includeInterim(request.excludeInterim == false)
.start(request.start).end(request.end).from(request.pageParams.getFrom()).size(request.pageParams.getSize())
.anomalyScoreThreshold(request.anomalyScoreFilter).sortField(request.sort).sortDescending(request.descending).build();
.influencerScoreThreshold(request.influencerScore).sortField(request.sort).sortDescending(request.descending).build();
jobProvider.influencers(request.jobId, query, page -> listener.onResponse(new Response(page)), listener::onFailure, client);
}
}

View File

@ -47,8 +47,8 @@ public final class InfluencersQueryBuilder {
return this;
}
public InfluencersQueryBuilder anomalyScoreThreshold(Double anomalyScoreFilter) {
influencersQuery.anomalyScoreFilter = anomalyScoreFilter;
public InfluencersQueryBuilder influencerScoreThreshold(Double influencerScoreFilter) {
influencersQuery.influencerScoreFilter = influencerScoreFilter;
return this;
}
@ -91,7 +91,7 @@ public final class InfluencersQueryBuilder {
private int from = 0;
private int size = DEFAULT_SIZE;
private boolean includeInterim = false;
private double anomalyScoreFilter = 0.0d;
private double influencerScoreFilter = 0.0d;
private String start;
private String end;
private String sortField = Influencer.INFLUENCER_SCORE.getPreferredName();
@ -109,8 +109,8 @@ public final class InfluencersQueryBuilder {
return includeInterim;
}
public double getAnomalyScoreFilter() {
return anomalyScoreFilter;
public double getInfluencerScoreFilter() {
return influencerScoreFilter;
}
public String getStart() {
@ -131,7 +131,7 @@ public final class InfluencersQueryBuilder {
@Override
public int hashCode() {
return Objects.hash(from, size, includeInterim, anomalyScoreFilter, start, end, sortField, sortDescending);
return Objects.hash(from, size, includeInterim, influencerScoreFilter, start, end, sortField, sortDescending);
}
@ -153,7 +153,7 @@ public final class InfluencersQueryBuilder {
Objects.equals(includeInterim, other.includeInterim) &&
Objects.equals(start, other.start) &&
Objects.equals(end, other.end) &&
Objects.equals(anomalyScoreFilter, other.anomalyScoreFilter) &&
Objects.equals(influencerScoreFilter, other.influencerScoreFilter) &&
Objects.equals(sortField, other.sortField) &&
this.sortDescending == other.sortDescending;
}

View File

@ -710,7 +710,7 @@ public class JobProvider {
Consumer<Exception> errorHandler, Client client) {
QueryBuilder fb = new ResultsFilterBuilder()
.timeRange(Result.TIMESTAMP.getPreferredName(), query.getStart(), query.getEnd())
.score(Bucket.ANOMALY_SCORE.getPreferredName(), query.getAnomalyScoreFilter())
.score(Influencer.INFLUENCER_SCORE.getPreferredName(), query.getInfluencerScoreFilter())
.interim(Bucket.IS_INTERIM.getPreferredName(), query.isIncludeInterim())
.build();

View File

@ -47,8 +47,8 @@ public class RestGetInfluencersAction extends BaseRestHandler {
request.setExcludeInterim(restRequest.paramAsBoolean(GetInfluencersAction.Request.EXCLUDE_INTERIM.getPreferredName(), false));
request.setPageParams(new PageParams(restRequest.paramAsInt(PageParams.FROM.getPreferredName(), PageParams.DEFAULT_FROM),
restRequest.paramAsInt(PageParams.SIZE.getPreferredName(), PageParams.DEFAULT_SIZE)));
request.setAnomalyScore(
Double.parseDouble(restRequest.param(GetInfluencersAction.Request.ANOMALY_SCORE.getPreferredName(), "0.0")));
request.setInfluencerScore(
Double.parseDouble(restRequest.param(GetInfluencersAction.Request.INFLUENCER_SCORE.getPreferredName(), "0.0")));
request.setSort(restRequest.param(GetInfluencersAction.Request.SORT_FIELD.getPreferredName(),
Influencer.INFLUENCER_SCORE.getPreferredName()));
request.setDescending(restRequest.paramAsBoolean(GetInfluencersAction.Request.DESCENDING_SORT.getPreferredName(), true));

View File

@ -29,7 +29,7 @@ public class GetInfluencersActionRequestTests extends AbstractStreamableXContent
request.setEnd(end);
}
if (randomBoolean()) {
request.setAnomalyScore(randomDouble());
request.setInfluencerScore(randomDouble());
}
if (randomBoolean()) {
request.setExcludeInterim(randomBoolean());

View File

@ -16,7 +16,7 @@ public class InfluencersQueryBuilderTests extends ESTestCase {
assertEquals(0, query.getFrom());
assertEquals(InfluencersQueryBuilder.DEFAULT_SIZE, query.getSize());
assertEquals(false, query.isIncludeInterim());
assertEquals(0.0, query.getAnomalyScoreFilter(), 0.0001);
assertEquals(0.0, query.getInfluencerScoreFilter(), 0.0001);
assertNull(query.getStart());
assertNull(query.getEnd());
assertEquals(Influencer.INFLUENCER_SCORE.getPreferredName(), query.getSortField());
@ -28,7 +28,7 @@ public class InfluencersQueryBuilderTests extends ESTestCase {
.from(20)
.size(40)
.includeInterim(true)
.anomalyScoreThreshold(50.0d)
.influencerScoreThreshold(50.0d)
.start("1000")
.end("2000")
.sortField("anomaly_score")
@ -38,7 +38,7 @@ public class InfluencersQueryBuilderTests extends ESTestCase {
assertEquals(20, query.getFrom());
assertEquals(40, query.getSize());
assertEquals(true, query.isIncludeInterim());
assertEquals(50.0d, query.getAnomalyScoreFilter(), 0.00001);
assertEquals(50.0d, query.getInfluencerScoreFilter(), 0.00001);
assertEquals("1000", query.getStart());
assertEquals("2000", query.getEnd());
assertEquals("anomaly_score", query.getSortField());
@ -50,7 +50,7 @@ public class InfluencersQueryBuilderTests extends ESTestCase {
.from(20)
.size(40)
.includeInterim(true)
.anomalyScoreThreshold(50.0d)
.influencerScoreThreshold(50.0d)
.start("1000")
.end("2000");
@ -58,7 +58,7 @@ public class InfluencersQueryBuilderTests extends ESTestCase {
.from(20)
.size(40)
.includeInterim(true)
.anomalyScoreThreshold(50.0d)
.influencerScoreThreshold(50.0d)
.start("1000")
.end("2000");
@ -70,7 +70,7 @@ public class InfluencersQueryBuilderTests extends ESTestCase {
query2.from(20)
.size(40)
.includeInterim(true)
.anomalyScoreThreshold(50.0d)
.influencerScoreThreshold(50.0d)
.start("1000")
.end("2000");
assertEquals(query.build(), query2.build());
@ -79,7 +79,7 @@ public class InfluencersQueryBuilderTests extends ESTestCase {
query2.from(20)
.size(40)
.includeInterim(true)
.anomalyScoreThreshold(50.1d)
.influencerScoreThreshold(50.1d)
.start("1000")
.end("2000");
assertFalse(query.build().equals(query2.build()));

View File

@ -738,7 +738,7 @@ public class JobProviderTests extends ESTestCase {
@SuppressWarnings({"unchecked", "rawtypes"})
QueryPage<Influencer>[] holder = new QueryPage[1];
InfluencersQuery query = new InfluencersQueryBuilder().from(from).size(size).start("0").end("0").sortField("sort")
.sortDescending(true).anomalyScoreThreshold(0.0).includeInterim(true).build();
.sortDescending(true).influencerScoreThreshold(0.0).includeInterim(true).build();
provider.influencers(jobId, query, page -> holder[0] = page, RuntimeException::new, client);
QueryPage<Influencer> page = holder[0];
assertEquals(2L, page.count());

View File

@ -1,7 +1,7 @@
setup:
- do:
xpack.ml.put_job:
job_id: farequote
job_id: get-influencers-test
body: >
{
"analysis_config" : {
@ -15,16 +15,16 @@ setup:
- do:
index:
index: .ml-anomalies-farequote
index: .ml-anomalies-get-influencers-test
type: result
id: farequote_1464739200000_1_1
id: get-influencers-test_1464739200000_1_1
body:
{
"job_id": "farequote",
"job_id": "get-influencers-test",
"timestamp": "2016-06-01T00:00:00Z",
"influencer_field_name": "foo",
"influencer_field_value": "bar",
"influencer_score": 80.0,
"influencer_score": 50.0,
"result_type" : "influencer",
"bucket_span" : 1,
"sequence_num" : 1
@ -32,60 +32,84 @@ setup:
- do:
index:
index: .ml-anomalies-farequote
index: .ml-anomalies-get-influencers-test
type: result
id: farequote_1464825600000_1_2
id: get-influencers-test_1464825600000_1_2
body:
{
"job_id": "farequote",
"job_id": "get-influencers-test",
"timestamp": "2016-06-02T00:00:00Z",
"influencer_field_name": "foo",
"influencer_field_value": "zoo",
"influencer_score": 50.0,
"influencer_score": 80.0,
"result_type" : "influencer",
"bucket_span" : 1,
"sequence_num" : 2,
"is_interim": true
}
- do:
index:
index: .ml-anomalies-get-influencers-test
type: result
id: get-influencers-test_1464912000000_1_3
body:
{
"job_id": "get-influencers-test",
"timestamp": "2016-06-03T00:00:00Z",
"influencer_field_name": "foo",
"influencer_field_value": "zoo",
"influencer_score": 60.0,
"result_type" : "influencer",
"bucket_span" : 1,
"sequence_num" : 2
}
- do:
indices.refresh:
index: .ml-anomalies-farequote
index: .ml-anomalies-get-influencers-test
---
"Test result influencers api":
- do:
xpack.ml.get_influencers:
job_id: "farequote"
job_id: "get-influencers-test"
- match: { count: 2 }
- match: { influencers.0.timestamp: 1464739200000 }
- match: { influencers.1.timestamp: 1464825600000 }
- match: { count: 3 }
- match: { influencers.0.influencer_score: 80 }
- match: { influencers.0.timestamp: 1464825600000 }
- match: { influencers.1.influencer_score: 60 }
- match: { influencers.1.timestamp: 1464912000000 }
- match: { influencers.2.influencer_score: 50 }
- match: { influencers.2.timestamp: 1464739200000 }
---
"Test get influencers given exclude_interim false":
- do:
xpack.ml.get_influencers:
job_id: "farequote"
job_id: "get-influencers-test"
exclude_interim: false
- match: { count: 2 }
- match: { count: 3 }
---
"Test get influencers given exclude_interim true":
- do:
xpack.ml.get_influencers:
job_id: "farequote"
job_id: "get-influencers-test"
exclude_interim: true
- match: { count: 1 }
- match: { influencers.0.timestamp: 1464739200000 }
- match: { count: 2 }
- match: { influencers.0.timestamp: 1464912000000 }
- match: { influencers.0.is_interim: false }
- match: { influencers.1.timestamp: 1464739200000 }
- match: { influencers.1.is_interim: false }
---
"Test result influencers api with time range":
- do:
xpack.ml.get_influencers:
job_id: "farequote"
job_id: "get-influencers-test"
start: "2016-06-01T00:00:00Z"
end: "2016-06-01T01:00:00Z"
@ -98,3 +122,35 @@ setup:
catch: missing
xpack.ml.get_influencers:
job_id: "non-existent-job"
---
"Test get influencers api with influencer score filter":
- do:
xpack.ml.get_influencers:
job_id: "get-influencers-test"
influencer_score: 70
- match: { count: 1 }
- match: { influencers.0.timestamp: 1464825600000 }
---
"Test get influencers api sort":
- do:
xpack.ml.get_influencers:
job_id: "get-influencers-test"
desc: false
- match: { count: 3 }
- match: { influencers.0.influencer_score: 50 }
- match: { influencers.1.influencer_score: 60 }
- match: { influencers.2.influencer_score: 80}
- do:
xpack.ml.get_influencers:
job_id: "get-influencers-test"
sort: timestamp
- match: { count: 3 }
- match: { influencers.0.timestamp: 1464912000000 }
- match: { influencers.1.timestamp: 1464825600000 }
- match: { influencers.2.timestamp: 1464739200000 }