Skip to content

Commit 0fe9787

Browse files
authored
[ML] adding result_type and mlcategory fields to category definitions (#63326)
To easy correlation between anomaly results and category definitions, this commit adds a new keyword mapped field `mlcategory`. This field is always the same as the `category_id` field (which is mapped as a long). But since anomaly results store the `mlcategory` as a keyword, it simplifies queries if category_definitions also had this field as a keyword. The stored JSON is a `string`. Additionally, this commit adds a `result_type: category_definition` entry to category definition documents. This will help simplify and unify result queries in the future. closes #60108
1 parent 1db311e commit 0fe9787

File tree

4 files changed

+15
-0
lines changed

4 files changed

+15
-0
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/results/CategoryDefinition.java

+7
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public class CategoryDefinition implements ToXContentObject, Writeable {
4040
public static final ParseField GROK_PATTERN = new ParseField("grok_pattern");
4141
public static final ParseField NUM_MATCHES = new ParseField("num_matches");
4242
public static final ParseField PREFERRED_TO_CATEGORIES = new ParseField("preferred_to_categories");
43+
public static final ParseField MLCATEGORY = new ParseField("mlcategory");
4344

4445
// Used for QueryPage
4546
public static final ParseField RESULTS_FIELD = new ParseField("categories");
@@ -62,6 +63,8 @@ private static ConstructingObjectParser<CategoryDefinition, Void> createParser(b
6263
parser.declareString(CategoryDefinition::setGrokPattern, GROK_PATTERN);
6364
parser.declareLongArray(CategoryDefinition::setPreferredToCategories, PREFERRED_TO_CATEGORIES);
6465
parser.declareLong(CategoryDefinition::setNumMatches, NUM_MATCHES);
66+
parser.declareString((cd, rt) -> { /*Ignore as it is always category_definition*/ }, Result.RESULT_TYPE);
67+
parser.declareString((cd, mc) -> { /*Ignore as it is always equal to category_id*/ }, MLCATEGORY);
6568
return parser;
6669
}
6770

@@ -246,6 +249,10 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
246249
if (partitionFieldName != null && partitionFieldValue != null && ReservedFieldNames.isValidFieldName(partitionFieldName)) {
247250
builder.field(partitionFieldName, partitionFieldValue);
248251
}
252+
// Even though category_definitions now have a result type, queries need for category definition values
253+
// still need to be done by looking for the category_id field. At least until 9.x
254+
builder.field(Result.RESULT_TYPE.getPreferredName(), TYPE.getPreferredName());
255+
builder.field(MLCATEGORY.getPreferredName(), String.valueOf(categoryId));
249256

250257
builder.endObject();
251258
return builder;

x-pack/plugin/core/src/main/resources/org/elasticsearch/xpack/core/ml/anomalydetection/results_index_mappings.json

+3
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,9 @@
333333
"missing_field_count" : {
334334
"type" : "long"
335335
},
336+
"mlcategory": {
337+
"type": "keyword"
338+
},
336339
"model_bytes" : {
337340
"type" : "long"
338341
},

x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/job/persistence/ElasticsearchMappingsTests.java

+3
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ public void testResultsMappingReservedFields() throws Exception {
9595
overridden.add(Quantiles.TYPE.getPreferredName());
9696
overridden.add(TimingStats.TYPE.getPreferredName());
9797
overridden.add(DatafeedTimingStats.TYPE.getPreferredName());
98+
// This is a special case so that categorical job results can be paired easily with anomaly results
99+
// This is acceptable as both mappings are keyword for the results documents and for category definitions
100+
overridden.add(CategoryDefinition.MLCATEGORY.getPreferredName());
98101

99102
Set<String> expected = collectResultsDocFieldNames();
100103
expected.removeAll(overridden);

x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/persistence/JobResultsProvider.java

+2
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,8 @@ public void categoryDefinitions(String jobId, Long categoryId, String partitionF
825825
if (categoryId != null) {
826826
categoryIdQuery = QueryBuilders.termQuery(CategoryDefinition.CATEGORY_ID.getPreferredName(), categoryId);
827827
} else if (from != null && size != null) {
828+
// Note: Even though category definitions currently have a result_type field, this was not the case for older versions
829+
// So, until at least 9.x, this existsQuery is still the preferred way to gather category definition objects
828830
categoryIdQuery = QueryBuilders.existsQuery(CategoryDefinition.CATEGORY_ID.getPreferredName());
829831
sourceBuilder.from(from).size(size)
830832
.sort(new FieldSortBuilder(CategoryDefinition.CATEGORY_ID.getPreferredName()).order(SortOrder.ASC));

0 commit comments

Comments
 (0)