Skip to content

Commit 7621f45

Browse files
[ML] adding result_type and mlcategory fields to category definitions (#63326) (#63412)
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 Co-authored-by: Elastic Machine <[email protected]>
1 parent 144b587 commit 7621f45

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public class CategoryDefinition implements ToXContentObject, Writeable {
4141
public static final ParseField GROK_PATTERN = new ParseField("grok_pattern");
4242
public static final ParseField NUM_MATCHES = new ParseField("num_matches");
4343
public static final ParseField PREFERRED_TO_CATEGORIES = new ParseField("preferred_to_categories");
44+
public static final ParseField MLCATEGORY = new ParseField("mlcategory");
4445

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

@@ -259,6 +262,10 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
259262
if (partitionFieldName != null && partitionFieldValue != null && ReservedFieldNames.isValidFieldName(partitionFieldName)) {
260263
builder.field(partitionFieldName, partitionFieldValue);
261264
}
265+
// Even though category_definitions now have a result type, queries need for category definition values
266+
// still need to be done by looking for the category_id field. At least until 9.x
267+
builder.field(Result.RESULT_TYPE.getPreferredName(), TYPE.getPreferredName());
268+
builder.field(MLCATEGORY.getPreferredName(), String.valueOf(categoryId));
262269

263270
builder.endObject();
264271
return builder;

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

Lines changed: 3 additions & 0 deletions
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

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

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

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,8 @@ public void categoryDefinitions(String jobId, Long categoryId, String partitionF
842842
if (categoryId != null) {
843843
categoryIdQuery = QueryBuilders.termQuery(CategoryDefinition.CATEGORY_ID.getPreferredName(), categoryId);
844844
} else if (from != null && size != null) {
845+
// Note: Even though category definitions currently have a result_type field, this was not the case for older versions
846+
// So, until at least 9.x, this existsQuery is still the preferred way to gather category definition objects
845847
categoryIdQuery = QueryBuilders.existsQuery(CategoryDefinition.CATEGORY_ID.getPreferredName());
846848
sourceBuilder.from(from).size(size)
847849
.sort(new FieldSortBuilder(CategoryDefinition.CATEGORY_ID.getPreferredName()).order(SortOrder.ASC));

0 commit comments

Comments
 (0)