Skip to content

Commit 403a8e3

Browse files
committed
[ML] Split up data visualizer model, remove Logger
1 parent aaf142c commit 403a8e3

File tree

13 files changed

+1337
-1046
lines changed

13 files changed

+1337
-1046
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { estypes } from '@elastic/elasticsearch';
9+
import { get } from 'lodash';
10+
import { IScopedClusterClient } from 'kibana/server';
11+
import { AggCardinality, Aggs, FieldData } from '../../types';
12+
import {
13+
buildBaseFilterCriteria,
14+
buildSamplerAggregation,
15+
getSafeAggregationName,
16+
getSamplerAggregationsResponsePath,
17+
} from '../../../common/utils/query_utils';
18+
import { getDatafeedAggregations } from '../../../common/utils/datafeed_utils';
19+
import { isPopulatedObject } from '../../../common/utils/object_utils';
20+
21+
export const checkAggregatableFieldsExist = async (
22+
client: IScopedClusterClient,
23+
indexPatternTitle: string,
24+
query: any,
25+
aggregatableFields: string[],
26+
samplerShardSize: number,
27+
timeFieldName: string | undefined,
28+
earliestMs?: number,
29+
latestMs?: number,
30+
datafeedConfig?: estypes.Datafeed,
31+
runtimeMappings?: estypes.RuntimeFields
32+
) => {
33+
const { asCurrentUser } = client;
34+
35+
const index = indexPatternTitle;
36+
const size = 0;
37+
const filterCriteria = buildBaseFilterCriteria(timeFieldName, earliestMs, latestMs, query);
38+
const datafeedAggregations = getDatafeedAggregations(datafeedConfig);
39+
40+
// Value count aggregation faster way of checking if field exists than using
41+
// filter aggregation with exists query.
42+
const aggs: Aggs = datafeedAggregations !== undefined ? { ...datafeedAggregations } : {};
43+
44+
// Combine runtime fields from the index pattern as well as the datafeed
45+
const combinedRuntimeMappings: estypes.RuntimeFields = {
46+
...(isPopulatedObject(runtimeMappings) ? runtimeMappings : {}),
47+
...(isPopulatedObject(datafeedConfig) && isPopulatedObject(datafeedConfig.runtime_mappings)
48+
? datafeedConfig.runtime_mappings
49+
: {}),
50+
};
51+
52+
aggregatableFields.forEach((field, i) => {
53+
const safeFieldName = getSafeAggregationName(field, i);
54+
aggs[`${safeFieldName}_count`] = {
55+
filter: { exists: { field } },
56+
};
57+
58+
let cardinalityField: AggCardinality;
59+
if (datafeedConfig?.script_fields?.hasOwnProperty(field)) {
60+
cardinalityField = aggs[`${safeFieldName}_cardinality`] = {
61+
cardinality: { script: datafeedConfig?.script_fields[field].script },
62+
};
63+
} else {
64+
cardinalityField = {
65+
cardinality: { field },
66+
};
67+
}
68+
aggs[`${safeFieldName}_cardinality`] = cardinalityField;
69+
});
70+
71+
const searchBody = {
72+
query: {
73+
bool: {
74+
filter: filterCriteria,
75+
},
76+
},
77+
...(isPopulatedObject(aggs) ? { aggs: buildSamplerAggregation(aggs, samplerShardSize) } : {}),
78+
...(isPopulatedObject(combinedRuntimeMappings)
79+
? { runtime_mappings: combinedRuntimeMappings }
80+
: {}),
81+
};
82+
83+
const { body } = await asCurrentUser.search({
84+
index,
85+
track_total_hits: true,
86+
size,
87+
body: searchBody,
88+
});
89+
90+
const aggregations = body.aggregations;
91+
// @ts-expect-error incorrect search response type
92+
const totalCount = body.hits.total.value;
93+
const stats = {
94+
totalCount,
95+
aggregatableExistsFields: [] as FieldData[],
96+
aggregatableNotExistsFields: [] as FieldData[],
97+
};
98+
99+
const aggsPath = getSamplerAggregationsResponsePath(samplerShardSize);
100+
const sampleCount =
101+
samplerShardSize > 0 ? get(aggregations, ['sample', 'doc_count'], 0) : totalCount;
102+
aggregatableFields.forEach((field, i) => {
103+
const safeFieldName = getSafeAggregationName(field, i);
104+
const count = get(aggregations, [...aggsPath, `${safeFieldName}_count`, 'doc_count'], 0);
105+
if (count > 0) {
106+
const cardinality = get(
107+
aggregations,
108+
[...aggsPath, `${safeFieldName}_cardinality`, 'value'],
109+
0
110+
);
111+
stats.aggregatableExistsFields.push({
112+
fieldName: field,
113+
existsInDocs: true,
114+
stats: {
115+
sampleCount,
116+
count,
117+
cardinality,
118+
},
119+
});
120+
} else {
121+
if (
122+
datafeedConfig?.script_fields?.hasOwnProperty(field) ||
123+
datafeedConfig?.runtime_mappings?.hasOwnProperty(field)
124+
) {
125+
const cardinality = get(
126+
aggregations,
127+
[...aggsPath, `${safeFieldName}_cardinality`, 'value'],
128+
0
129+
);
130+
stats.aggregatableExistsFields.push({
131+
fieldName: field,
132+
existsInDocs: true,
133+
stats: {
134+
sampleCount,
135+
count,
136+
cardinality,
137+
},
138+
});
139+
} else {
140+
stats.aggregatableNotExistsFields.push({
141+
fieldName: field,
142+
existsInDocs: false,
143+
});
144+
}
145+
}
146+
});
147+
148+
return stats;
149+
};
150+
151+
export const checkNonAggregatableFieldExists = async (
152+
client: IScopedClusterClient,
153+
indexPatternTitle: string,
154+
query: any,
155+
field: string,
156+
timeFieldName: string | undefined,
157+
earliestMs: number | undefined,
158+
latestMs: number | undefined,
159+
runtimeMappings?: estypes.RuntimeFields
160+
) => {
161+
const { asCurrentUser } = client;
162+
const index = indexPatternTitle;
163+
const size = 0;
164+
const filterCriteria = buildBaseFilterCriteria(timeFieldName, earliestMs, latestMs, query);
165+
166+
const searchBody = {
167+
query: {
168+
bool: {
169+
filter: filterCriteria,
170+
},
171+
},
172+
...(isPopulatedObject(runtimeMappings) ? { runtime_mappings: runtimeMappings } : {}),
173+
};
174+
filterCriteria.push({ exists: { field } });
175+
176+
const { body } = await asCurrentUser.search({
177+
index,
178+
size,
179+
body: searchBody,
180+
});
181+
// @ts-expect-error incorrect search response type
182+
return body.hits.total.value > 0;
183+
};

x-pack/plugins/file_upload/server/types.ts renamed to x-pack/plugins/data_visualizer/server/models/data_visualizer/constants.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
* 2.0.
66
*/
77

8-
import { SecurityPluginStart } from '../..//security/server';
8+
export const SAMPLER_TOP_TERMS_THRESHOLD = 100000;
9+
export const SAMPLER_TOP_TERMS_SHARD_SIZE = 5000;
10+
export const AGGREGATABLE_EXISTS_REQUEST_BATCH_SIZE = 200;
11+
export const FIELDS_REQUEST_BATCH_SIZE = 10;
912

10-
export interface StartDeps {
11-
security?: SecurityPluginStart;
12-
}
13+
export const MAX_CHART_COLUMNS = 20;

0 commit comments

Comments
 (0)