diff --git a/src/main/java/org/opensearch/ad/model/ADTask.java b/src/main/java/org/opensearch/ad/model/ADTask.java index d51d39022..19fc87682 100644 --- a/src/main/java/org/opensearch/ad/model/ADTask.java +++ b/src/main/java/org/opensearch/ad/model/ADTask.java @@ -344,7 +344,8 @@ public static ADTask parse(XContentParser parser, String taskId) throws IOExcept detector.getRules(), detector.getCustomResultIndexMinSize(), detector.getCustomResultIndexMinAge(), - detector.getCustomResultIndexTTL() + detector.getCustomResultIndexTTL(), + detector.getFlattenResultIndexMapping() ); return new Builder() .taskId(parsedTaskId) diff --git a/src/main/java/org/opensearch/ad/model/AnomalyDetector.java b/src/main/java/org/opensearch/ad/model/AnomalyDetector.java index f5de3bba6..d88ffa653 100644 --- a/src/main/java/org/opensearch/ad/model/AnomalyDetector.java +++ b/src/main/java/org/opensearch/ad/model/AnomalyDetector.java @@ -150,6 +150,7 @@ public Integer getShingleSize(Integer customShingleSize) { * @param customResultIndexMinSize custom result index lifecycle management min size condition * @param customResultIndexMinAge custom result index lifecycle management min age condition * @param customResultIndexTTL custom result index lifecycle management ttl + * @param flattenResultIndexMapping flag to indicate whether to flatten result index mapping or not */ public AnomalyDetector( String detectorId, @@ -176,7 +177,8 @@ public AnomalyDetector( List rules, Integer customResultIndexMinSize, Integer customResultIndexMinAge, - Integer customResultIndexTTL + Integer customResultIndexTTL, + Boolean flattenResultIndexMapping ) { super( detectorId, @@ -203,7 +205,8 @@ public AnomalyDetector( historyIntervals, customResultIndexMinSize, customResultIndexMinAge, - customResultIndexTTL + customResultIndexTTL, + flattenResultIndexMapping ); checkAndThrowValidationErrors(ValidationAspect.DETECTOR); @@ -280,6 +283,7 @@ public AnomalyDetector(StreamInput input) throws IOException { this.customResultIndexMinSize = input.readOptionalInt(); this.customResultIndexMinAge = input.readOptionalInt(); this.customResultIndexTTL = input.readOptionalInt(); + this.flattenResultIndexMapping = input.readOptionalBoolean(); } public XContentBuilder toXContent(XContentBuilder builder) throws IOException { @@ -345,6 +349,7 @@ public void writeTo(StreamOutput output) throws IOException { output.writeOptionalInt(customResultIndexMinSize); output.writeOptionalInt(customResultIndexMinAge); output.writeOptionalInt(customResultIndexTTL); + output.writeOptionalBoolean(flattenResultIndexMapping); } @Override @@ -441,6 +446,7 @@ public static AnomalyDetector parse( Integer customResultIndexMinSize = null; Integer customResultIndexMinAge = null; Integer customResultIndexTTL = null; + Boolean flattenResultIndexMapping = null; ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.currentToken(), parser); while (parser.nextToken() != XContentParser.Token.END_OBJECT) { @@ -575,6 +581,9 @@ public static AnomalyDetector parse( case RESULT_INDEX_FIELD_TTL: customResultIndexTTL = onlyParseNumberValue(parser); break; + case FLATTEN_RESULT_INDEX_MAPPING: + flattenResultIndexMapping = onlyParseBooleanValue(parser); + break; default: parser.skipChildren(); break; @@ -605,7 +614,8 @@ public static AnomalyDetector parse( rules, customResultIndexMinSize, customResultIndexMinAge, - customResultIndexTTL + customResultIndexTTL, + flattenResultIndexMapping ); detector.setDetectionDateRange(detectionDateRange); return detector; @@ -692,4 +702,11 @@ private static Integer onlyParseNumberValue(XContentParser parser) throws IOExce } return null; } + + private static Boolean onlyParseBooleanValue(XContentParser parser) throws IOException { + if (parser.currentToken() == XContentParser.Token.VALUE_BOOLEAN) { + return parser.booleanValue(); + } + return null; + } } diff --git a/src/main/java/org/opensearch/ad/rest/handler/AbstractAnomalyDetectorActionHandler.java b/src/main/java/org/opensearch/ad/rest/handler/AbstractAnomalyDetectorActionHandler.java index ef2b7d754..87abf5d1f 100644 --- a/src/main/java/org/opensearch/ad/rest/handler/AbstractAnomalyDetectorActionHandler.java +++ b/src/main/java/org/opensearch/ad/rest/handler/AbstractAnomalyDetectorActionHandler.java @@ -239,7 +239,8 @@ protected AnomalyDetector copyConfig(User user, Config config) { detector.getRules(), config.getCustomResultIndexMinSize(), config.getCustomResultIndexMinAge(), - config.getCustomResultIndexTTL() + config.getCustomResultIndexTTL(), + config.getFlattenResultIndexMapping() ); } diff --git a/src/main/java/org/opensearch/forecast/model/ForecastTask.java b/src/main/java/org/opensearch/forecast/model/ForecastTask.java index 33bd114ab..bb6a53d50 100644 --- a/src/main/java/org/opensearch/forecast/model/ForecastTask.java +++ b/src/main/java/org/opensearch/forecast/model/ForecastTask.java @@ -342,7 +342,8 @@ public static ForecastTask parse(XContentParser parser, String taskId) throws IO forecaster.getHistoryIntervals(), forecaster.getCustomResultIndexMinSize(), forecaster.getCustomResultIndexMinAge(), - forecaster.getCustomResultIndexTTL() + forecaster.getCustomResultIndexTTL(), + forecaster.getFlattenResultIndexMapping() ); return new Builder() .taskId(parsedTaskId) diff --git a/src/main/java/org/opensearch/forecast/model/Forecaster.java b/src/main/java/org/opensearch/forecast/model/Forecaster.java index 8feb24795..0cac28d8b 100644 --- a/src/main/java/org/opensearch/forecast/model/Forecaster.java +++ b/src/main/java/org/opensearch/forecast/model/Forecaster.java @@ -134,7 +134,8 @@ public Forecaster( Integer historyIntervals, Integer customResultIndexMinSize, Integer customResultIndexMinAge, - Integer customResultIndexTTL + Integer customResultIndexTTL, + Boolean flattenResultIndexMapping ) { super( forecasterId, @@ -161,7 +162,8 @@ public Forecaster( historyIntervals, customResultIndexMinSize, customResultIndexMinAge, - customResultIndexTTL + customResultIndexTTL, + flattenResultIndexMapping ); checkAndThrowValidationErrors(ValidationAspect.FORECASTER); @@ -303,6 +305,7 @@ public static Forecaster parse( Integer customResultIndexMinSize = null; Integer customResultIndexMinAge = null; Integer customResultIndexTTL = null; + Boolean flattenResultIndexMapping = null; ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.currentToken(), parser); while (parser.nextToken() != XContentParser.Token.END_OBJECT) { @@ -431,6 +434,9 @@ public static Forecaster parse( case RESULT_INDEX_FIELD_TTL: customResultIndexTTL = parser.intValue(); break; + case FLATTEN_RESULT_INDEX_MAPPING: + flattenResultIndexMapping = parser.booleanValue(); + break; default: parser.skipChildren(); break; @@ -461,7 +467,8 @@ public static Forecaster parse( historyIntervals, customResultIndexMinSize, customResultIndexMinAge, - customResultIndexTTL + customResultIndexTTL, + flattenResultIndexMapping ); return forecaster; } diff --git a/src/main/java/org/opensearch/forecast/rest/handler/AbstractForecasterActionHandler.java b/src/main/java/org/opensearch/forecast/rest/handler/AbstractForecasterActionHandler.java index 92bbf9325..75fab31c4 100644 --- a/src/main/java/org/opensearch/forecast/rest/handler/AbstractForecasterActionHandler.java +++ b/src/main/java/org/opensearch/forecast/rest/handler/AbstractForecasterActionHandler.java @@ -257,7 +257,8 @@ protected Config copyConfig(User user, Config config) { config.getHistoryIntervals(), config.getCustomResultIndexMinSize(), config.getCustomResultIndexMinAge(), - config.getCustomResultIndexTTL() + config.getCustomResultIndexTTL(), + config.getFlattenResultIndexMapping() ); } diff --git a/src/main/java/org/opensearch/timeseries/model/Config.java b/src/main/java/org/opensearch/timeseries/model/Config.java index 1dfdfb54c..d4e61a040 100644 --- a/src/main/java/org/opensearch/timeseries/model/Config.java +++ b/src/main/java/org/opensearch/timeseries/model/Config.java @@ -79,6 +79,7 @@ public abstract class Config implements Writeable, ToXContentObject { public static final String RESULT_INDEX_FIELD_MIN_SIZE = "result_index_min_size"; public static final String RESULT_INDEX_FIELD_MIN_AGE = "result_index_min_age"; public static final String RESULT_INDEX_FIELD_TTL = "result_index_ttl"; + public static final String FLATTEN_RESULT_INDEX_MAPPING = "flatten_result_index_mapping"; protected String id; protected Long version; @@ -118,6 +119,7 @@ public abstract class Config implements Writeable, ToXContentObject { protected Integer customResultIndexMinSize; protected Integer customResultIndexMinAge; protected Integer customResultIndexTTL; + protected Boolean flattenResultIndexMapping; public static String INVALID_RESULT_INDEX_NAME_SIZE = "Result index name size must contains less than " + MAX_RESULT_INDEX_NAME_SIZE @@ -148,7 +150,8 @@ protected Config( Integer historyIntervals, Integer customResultIndexMinSize, Integer customResultIndexMinAge, - Integer customResultIndexTTL + Integer customResultIndexTTL, + Boolean flattenResultIndexMapping ) { if (Strings.isBlank(name)) { errorMessage = CommonMessages.EMPTY_NAME; @@ -267,6 +270,7 @@ protected Config( this.customResultIndexMinSize = Strings.trimToNull(resultIndex) == null ? null : customResultIndexMinSize; this.customResultIndexMinAge = Strings.trimToNull(resultIndex) == null ? null : customResultIndexMinAge; this.customResultIndexTTL = Strings.trimToNull(resultIndex) == null ? null : customResultIndexTTL; + this.flattenResultIndexMapping = Strings.trimToNull(resultIndex) == null ? null : flattenResultIndexMapping; } public int suggestHistory() { @@ -310,6 +314,7 @@ public Config(StreamInput input) throws IOException { this.customResultIndexMinSize = input.readOptionalInt(); this.customResultIndexMinAge = input.readOptionalInt(); this.customResultIndexTTL = input.readOptionalInt(); + this.flattenResultIndexMapping = input.readOptionalBoolean(); } /* @@ -362,6 +367,7 @@ public void writeTo(StreamOutput output) throws IOException { output.writeOptionalInt(customResultIndexMinSize); output.writeOptionalInt(customResultIndexMinAge); output.writeOptionalInt(customResultIndexTTL); + output.writeOptionalBoolean(flattenResultIndexMapping); } public boolean invalidShingleSizeRange(Integer shingleSizeToTest) { @@ -418,7 +424,8 @@ public boolean equals(Object o) { && Objects.equal(historyIntervals, config.historyIntervals) && Objects.equal(customResultIndexMinSize, config.customResultIndexMinSize) && Objects.equal(customResultIndexMinAge, config.customResultIndexMinAge) - && Objects.equal(customResultIndexTTL, config.customResultIndexTTL); + && Objects.equal(customResultIndexTTL, config.customResultIndexTTL) + && Objects.equal(flattenResultIndexMapping, config.flattenResultIndexMapping); } @Generated @@ -445,7 +452,8 @@ public int hashCode() { historyIntervals, customResultIndexMinSize, customResultIndexMinAge, - customResultIndexTTL + customResultIndexTTL, + flattenResultIndexMapping ); } @@ -494,6 +502,9 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws if (customResultIndexTTL != null) { builder.field(RESULT_INDEX_FIELD_TTL, customResultIndexTTL); } + if (flattenResultIndexMapping != null) { + builder.field(FLATTEN_RESULT_INDEX_MAPPING, flattenResultIndexMapping); + } return builder; } @@ -702,6 +713,10 @@ public Integer getCustomResultIndexTTL() { return customResultIndexTTL; } + public Boolean getFlattenResultIndexMapping() { + return flattenResultIndexMapping; + } + /** * Identifies redundant feature names. * @@ -756,6 +771,7 @@ public String toString() { .append("customResultIndexMinSize", customResultIndexMinSize) .append("customResultIndexMinAge", customResultIndexMinAge) .append("customResultIndexTTL", customResultIndexTTL) + .append("flattenResultIndexMapping", flattenResultIndexMapping) .toString(); } } diff --git a/src/test/java/org/opensearch/ad/AnomalyDetectorRestTestCase.java b/src/test/java/org/opensearch/ad/AnomalyDetectorRestTestCase.java index 5500d28cc..627be0240 100644 --- a/src/test/java/org/opensearch/ad/AnomalyDetectorRestTestCase.java +++ b/src/test/java/org/opensearch/ad/AnomalyDetectorRestTestCase.java @@ -314,7 +314,8 @@ public ToXContentObject[] getConfig(String detectorId, BasicHeader header, boole null, detector.getCustomResultIndexMinSize(), detector.getCustomResultIndexMinAge(), - detector.getCustomResultIndexTTL() + detector.getCustomResultIndexTTL(), + detector.getFlattenResultIndexMapping() ), detectorJob, historicalAdTask, @@ -640,7 +641,8 @@ protected AnomalyDetector cloneDetector(AnomalyDetector anomalyDetector, String null, anomalyDetector.getCustomResultIndexMinSize(), anomalyDetector.getCustomResultIndexMinAge(), - anomalyDetector.getCustomResultIndexTTL() + anomalyDetector.getCustomResultIndexTTL(), + anomalyDetector.getFlattenResultIndexMapping() ); return detector; } diff --git a/src/test/java/org/opensearch/ad/model/AnomalyDetectorTests.java b/src/test/java/org/opensearch/ad/model/AnomalyDetectorTests.java index 422c1be94..1244631d2 100644 --- a/src/test/java/org/opensearch/ad/model/AnomalyDetectorTests.java +++ b/src/test/java/org/opensearch/ad/model/AnomalyDetectorTests.java @@ -339,6 +339,7 @@ public void testInvalidShingleSize() throws Exception { null, null, null, + null, null ) ); @@ -374,6 +375,7 @@ public void testNullDetectorName() throws Exception { null, null, null, + null, null ) ); @@ -409,6 +411,7 @@ public void testBlankDetectorName() throws Exception { null, null, null, + null, null ) ); @@ -444,6 +447,7 @@ public void testNullTimeField() throws Exception { null, null, null, + null, null ) ); @@ -479,6 +483,7 @@ public void testNullIndices() throws Exception { null, null, null, + null, null ) ); @@ -514,6 +519,7 @@ public void testEmptyIndices() throws Exception { null, null, null, + null, null ) ); @@ -549,6 +555,7 @@ public void testNullDetectionInterval() throws Exception { null, null, null, + null, null ) ); @@ -583,6 +590,7 @@ public void testInvalidRecency() { null, null, null, + null, null ) ); @@ -618,6 +626,7 @@ public void testInvalidDetectionInterval() { null, null, null, + null, null ) ); @@ -653,6 +662,7 @@ public void testInvalidWindowDelay() { null, null, null, + null, null ) ); @@ -701,6 +711,7 @@ public void testGetShingleSize() throws IOException { null, null, null, + null, null ); assertEquals((int) anomalyDetector.getShingleSize(), 5); @@ -734,6 +745,7 @@ public void testGetShingleSizeReturnsDefaultValue() throws IOException { null, null, null, + null, null ); // seasonalityIntervals is not null and custom shingle size is null, use seasonalityIntervals to deterine shingle size @@ -764,6 +776,7 @@ public void testGetShingleSizeReturnsDefaultValue() throws IOException { null, null, null, + null, null ); // seasonalityIntervals is null and custom shingle size is null, use default shingle size @@ -796,6 +809,7 @@ public void testNullFeatureAttributes() throws IOException { null, null, null, + null, null ); assertNotNull(anomalyDetector.getFeatureAttributes()); @@ -828,6 +842,7 @@ public void testValidateResultIndex() throws IOException { null, null, null, + null, null ); String errorMessage = anomalyDetector.validateCustomResultIndex("abc"); @@ -916,6 +931,21 @@ public void testParseAnomalyDetector_withCustomIndex_withCustomResultIndexTTL() assertEquals(30, (int) parsedDetector.getCustomResultIndexTTL()); } + public void testParseAnomalyDetector_withCustomIndex_withFlattenResultIndexMapping() throws IOException { + String detectorString = "{\"name\":\"AhtYYGWTgqkzairTchcs\",\"description\":\"iIiAVPMyFgnFlEniLbMyfJxyoGvJAl\"," + + "\"time_field\":\"HmdFH\",\"indices\":[\"ffsBF\"],\"filter_query\":{\"bool\":{\"filter\":[{\"exists\":" + + "{\"field\":\"value\",\"boost\":1}}],\"adjust_pure_negative\":true,\"boost\":1}},\"window_delay\":" + + "{\"period\":{\"interval\":2,\"unit\":\"Minutes\"}},\"shingle_size\":8,\"schema_version\":-512063255," + + "\"feature_attributes\":[{\"feature_id\":\"OTYJs\",\"feature_name\":\"eYYCM\",\"feature_enabled\":false," + + "\"aggregation_query\":{\"XzewX\":{\"value_count\":{\"field\":\"ok\"}}}}],\"recency_emphasis\":3342," + + "\"history\":62,\"last_update_time\":1717192049845,\"category_field\":[\"Tcqcb\"],\"result_index\":" + + "\"opensearch-ad-plugin-result-test\",\"imputation_option\":{\"method\":\"FIXED_VALUES\",\"defaultFill\"" + + ":[],\"integerSensitive\":false},\"suggested_seasonality\":64,\"detection_interval\":{\"period\":" + + "{\"interval\":5,\"unit\":\"Minutes\"}},\"detector_type\":\"MULTI_ENTITY\",\"rules\":[],\"flatten_result_index_mapping\":true}"; + AnomalyDetector parsedDetector = AnomalyDetector.parse(TestHelpers.parser(detectorString), "id", 1L, null, null); + assertEquals(true, (boolean) parsedDetector.getFlattenResultIndexMapping()); + } + public void testSerializeAndDeserializeAnomalyDetector() throws IOException { // register writer and reader for type Feature Writeable.WriteableRegistry.registerWriter(Feature.class, (o, v) -> { diff --git a/src/test/java/org/opensearch/ad/rest/ADRestTestUtils.java b/src/test/java/org/opensearch/ad/rest/ADRestTestUtils.java index 9340bd9fc..f679d32b6 100644 --- a/src/test/java/org/opensearch/ad/rest/ADRestTestUtils.java +++ b/src/test/java/org/opensearch/ad/rest/ADRestTestUtils.java @@ -221,6 +221,7 @@ public static Response createAnomalyDetector( null, null, null, + null, null ); diff --git a/src/test/java/org/opensearch/ad/rest/AnomalyDetectorRestApiIT.java b/src/test/java/org/opensearch/ad/rest/AnomalyDetectorRestApiIT.java index dcabcf442..aef88a804 100644 --- a/src/test/java/org/opensearch/ad/rest/AnomalyDetectorRestApiIT.java +++ b/src/test/java/org/opensearch/ad/rest/AnomalyDetectorRestApiIT.java @@ -157,6 +157,7 @@ public void testCreateAnomalyDetectorWithDuplicateName() throws Exception { null, null, null, + null, null ); @@ -268,6 +269,7 @@ public void testUpdateAnomalyDetectorCategoryField() throws Exception { null, null, null, + null, null ); Exception ex = expectThrows( @@ -334,6 +336,7 @@ public void testUpdateAnomalyDetector() throws Exception { null, null, null, + null, null ); @@ -405,6 +408,7 @@ public void testUpdateAnomalyDetectorNameToExisting() throws Exception { null, null, null, + null, null ); @@ -453,6 +457,7 @@ public void testUpdateAnomalyDetectorNameToNew() throws Exception { null, null, null, + null, null ); @@ -507,6 +512,7 @@ public void testUpdateAnomalyDetectorWithNotExistingIndex() throws Exception { null, null, null, + null, null ); @@ -878,6 +884,7 @@ public void testUpdateAnomalyDetectorWithRunningAdJob() throws Exception { null, null, null, + null, null ); diff --git a/src/test/java/org/opensearch/ad/rest/HistoricalAnalysisRestApiIT.java b/src/test/java/org/opensearch/ad/rest/HistoricalAnalysisRestApiIT.java index 5b7cc322d..5cbf1ce36 100644 --- a/src/test/java/org/opensearch/ad/rest/HistoricalAnalysisRestApiIT.java +++ b/src/test/java/org/opensearch/ad/rest/HistoricalAnalysisRestApiIT.java @@ -344,7 +344,8 @@ private AnomalyDetector randomAnomalyDetector(AnomalyDetector detector) { null, detector.getCustomResultIndexMinSize(), detector.getCustomResultIndexMinAge(), - detector.getCustomResultIndexTTL() + detector.getCustomResultIndexTTL(), + detector.getFlattenResultIndexMapping() ); } diff --git a/src/test/java/org/opensearch/ad/rest/SecureADRestIT.java b/src/test/java/org/opensearch/ad/rest/SecureADRestIT.java index a63917f0f..cd744781e 100644 --- a/src/test/java/org/opensearch/ad/rest/SecureADRestIT.java +++ b/src/test/java/org/opensearch/ad/rest/SecureADRestIT.java @@ -293,6 +293,7 @@ public void testUpdateApiFilterByEnabledForAdmin() throws IOException { null, null, null, + null, null ); // User client has admin all access, and has "opensearch" backend role so client should be able to update detector @@ -347,6 +348,7 @@ public void testUpdateApiFilterByEnabled() throws IOException { null, null, null, + null, null ); enableFilterBy(); diff --git a/src/test/java/org/opensearch/ad/transport/AnomalyResultTransportActionTests.java b/src/test/java/org/opensearch/ad/transport/AnomalyResultTransportActionTests.java index f8208215f..2acc455be 100644 --- a/src/test/java/org/opensearch/ad/transport/AnomalyResultTransportActionTests.java +++ b/src/test/java/org/opensearch/ad/transport/AnomalyResultTransportActionTests.java @@ -226,6 +226,7 @@ private AnomalyDetector randomDetector(List indices, List featu null, null, null, + null, null ); } @@ -256,6 +257,7 @@ private AnomalyDetector randomHCDetector(List indices, List fea null, null, null, + null, null ); } diff --git a/src/test/java/org/opensearch/ad/transport/ForwardADTaskRequestTests.java b/src/test/java/org/opensearch/ad/transport/ForwardADTaskRequestTests.java index 6e93ef01a..fd16a288f 100644 --- a/src/test/java/org/opensearch/ad/transport/ForwardADTaskRequestTests.java +++ b/src/test/java/org/opensearch/ad/transport/ForwardADTaskRequestTests.java @@ -85,6 +85,7 @@ public void testNullDetectorIdAndTaskAction() throws IOException { null, null, null, + null, null ); ForwardADTaskRequest request = new ForwardADTaskRequest(detector, null, null, null, null, Version.V_2_1_0); diff --git a/src/test/java/org/opensearch/ad/transport/ValidateAnomalyDetectorTransportActionTests.java b/src/test/java/org/opensearch/ad/transport/ValidateAnomalyDetectorTransportActionTests.java index 7ba4680e7..bb234769a 100644 --- a/src/test/java/org/opensearch/ad/transport/ValidateAnomalyDetectorTransportActionTests.java +++ b/src/test/java/org/opensearch/ad/transport/ValidateAnomalyDetectorTransportActionTests.java @@ -402,6 +402,7 @@ public void testValidateAnomalyDetectorWithInvalidDetectorName() throws IOExcept null, null, null, + null, null ); ingestTestDataValidate(anomalyDetector.getIndices().get(0), Instant.now().minus(1, ChronoUnit.DAYS), 1, "error"); @@ -449,6 +450,7 @@ public void testValidateAnomalyDetectorWithDetectorNameTooLong() throws IOExcept null, null, null, + null, null ); ingestTestDataValidate(anomalyDetector.getIndices().get(0), Instant.now().minus(1, ChronoUnit.DAYS), 1, "error"); diff --git a/src/test/java/org/opensearch/forecast/model/ForecasterTests.java b/src/test/java/org/opensearch/forecast/model/ForecasterTests.java index 66af227ee..1c2a29029 100644 --- a/src/test/java/org/opensearch/forecast/model/ForecasterTests.java +++ b/src/test/java/org/opensearch/forecast/model/ForecasterTests.java @@ -59,6 +59,7 @@ public class ForecasterTests extends AbstractTimeSeriesTest { Integer customResultIndexMinSize = null; Integer customResultIndexMinAge = null; Integer customResultIndexTTL = null; + Boolean flattenResultIndexMapping = null; public void testForecasterConstructor() { ImputationOption imputationOption = TestHelpers.randomImputationOption(0); @@ -88,7 +89,8 @@ public void testForecasterConstructor() { randomIntBetween(1, 1000), customResultIndexMinSize, customResultIndexMinAge, - customResultIndexTTL + customResultIndexTTL, + flattenResultIndexMapping ); assertEquals(forecasterId, forecaster.getId()); @@ -141,7 +143,8 @@ public void testForecasterConstructorWithNullForecastInterval() { randomIntBetween(1, 1000), customResultIndexMinSize, customResultIndexMinAge, - customResultIndexTTL + customResultIndexTTL, + flattenResultIndexMapping ); }); @@ -179,7 +182,8 @@ public void testNegativeInterval() { randomIntBetween(1, 1000), customResultIndexMinSize, customResultIndexMinAge, - customResultIndexTTL + customResultIndexTTL, + flattenResultIndexMapping ); }); @@ -217,7 +221,8 @@ public void testMaxCategoryFieldsLimits() { randomIntBetween(1, 1000), customResultIndexMinSize, customResultIndexMinAge, - customResultIndexTTL + customResultIndexTTL, + flattenResultIndexMapping ); }); @@ -255,7 +260,8 @@ public void testBlankName() { randomIntBetween(1, 1000), customResultIndexMinSize, customResultIndexMinAge, - customResultIndexTTL + customResultIndexTTL, + flattenResultIndexMapping ); }); @@ -293,7 +299,8 @@ public void testInvalidCustomResultIndex() { randomIntBetween(1, 1000), customResultIndexMinSize, customResultIndexMinAge, - customResultIndexTTL + customResultIndexTTL, + flattenResultIndexMapping ); }); @@ -330,7 +337,8 @@ public void testValidCustomResultIndex() { randomIntBetween(1, 1000), customResultIndexMinSize, customResultIndexMinAge, - customResultIndexTTL + customResultIndexTTL, + flattenResultIndexMapping ); assertEquals(resultIndex, forecaster.getCustomResultIndexOrAlias()); @@ -365,7 +373,8 @@ public void testInvalidHorizon() { randomIntBetween(1, 1000), customResultIndexMinSize, customResultIndexMinAge, - customResultIndexTTL + customResultIndexTTL, + flattenResultIndexMapping ); }); @@ -466,4 +475,22 @@ public void testValidCustomResultIndex_withIndexConditions() throws IOException Forecaster parsedForecaster = Forecaster.parse(TestHelpers.parser(forecasterString)); assertEquals(forecaster, parsedForecaster); } + + public void testParseNullCustomResultIndex_nullFlattenResultIndexMapping() throws IOException { + Forecaster forecaster = TestHelpers.ForecasterBuilder.newInstance().setFlattenResultIndexMapping(null).build(); + String forecasterString = TestHelpers + .xContentBuilderToString(forecaster.toXContent(TestHelpers.builder(), ToXContent.EMPTY_PARAMS)); + LOG.info(forecasterString); + Forecaster parsedForecaster = Forecaster.parse(TestHelpers.parser(forecasterString)); + assertEquals(forecaster, parsedForecaster); + } + + public void testValidCustomResultIndex_withFlattenResultIndexMapping() throws IOException { + Forecaster forecaster = TestHelpers.ForecasterBuilder.newInstance().setFlattenResultIndexMapping(true).build(); + String forecasterString = TestHelpers + .xContentBuilderToString(forecaster.toXContent(TestHelpers.builder(), ToXContent.EMPTY_PARAMS)); + LOG.info(forecasterString); + Forecaster parsedForecaster = Forecaster.parse(TestHelpers.parser(forecasterString)); + assertEquals(forecaster, parsedForecaster); + } } diff --git a/src/test/java/org/opensearch/timeseries/TestHelpers.java b/src/test/java/org/opensearch/timeseries/TestHelpers.java index 22df12529..8423c630c 100644 --- a/src/test/java/org/opensearch/timeseries/TestHelpers.java +++ b/src/test/java/org/opensearch/timeseries/TestHelpers.java @@ -339,6 +339,7 @@ public static AnomalyDetector randomAnomalyDetector( new ArrayList(), null, null, + null, null ); } @@ -391,6 +392,7 @@ public static AnomalyDetector randomDetector( null, null, null, + null, null ); } @@ -453,6 +455,7 @@ public static AnomalyDetector randomAnomalyDetectorUsingCategoryFields( null, null, null, + null, null ); } @@ -491,6 +494,7 @@ public static AnomalyDetector randomAnomalyDetector(String timefield, String ind null, null, null, + null, null ); } @@ -521,6 +525,7 @@ public static AnomalyDetector randomAnomalyDetectorWithEmptyFeature() throws IOE null, null, null, + null, null ); } @@ -557,6 +562,7 @@ public static AnomalyDetector randomAnomalyDetectorWithInterval(TimeConfiguratio null, null, null, + null, null ); } @@ -727,6 +733,7 @@ public AnomalyDetector build() { null, null, null, + null, null ); } @@ -760,6 +767,7 @@ public static AnomalyDetector randomAnomalyDetectorWithInterval(TimeConfiguratio null, null, null, + null, null ); } @@ -1721,6 +1729,7 @@ public static class ForecasterBuilder { Integer customResultIndexMinSize; Integer customResultIndexMinAge; Integer customResultIndexTTL; + Boolean flattenResultIndexMapping; ForecasterBuilder() throws IOException { forecasterId = randomAlphaOfLength(10); @@ -1745,6 +1754,7 @@ public static class ForecasterBuilder { customResultIndexMinSize = null; customResultIndexMinAge = null; customResultIndexTTL = null; + flattenResultIndexMapping = null; } public static ForecasterBuilder newInstance() throws IOException { @@ -1851,6 +1861,11 @@ public ForecasterBuilder setCustomResultIndexTTL(Integer customResultIndexTTL) { return this; } + public ForecasterBuilder setFlattenResultIndexMapping(Boolean flattenResultIndexMapping) { + this.flattenResultIndexMapping = flattenResultIndexMapping; + return this; + } + public ForecasterBuilder setNullImputationOption() { this.imputationOption = null; return this; @@ -1887,7 +1902,8 @@ public Forecaster build() { randomIntBetween(1, 1000), customResultIndexMinSize, customResultIndexMinAge, - customResultIndexTTL + customResultIndexTTL, + flattenResultIndexMapping ); } } @@ -1919,6 +1935,7 @@ public static Forecaster randomForecaster() throws IOException { randomIntBetween(1, 1000), null, null, + null, null ); }