Skip to content

Commit 39728e2

Browse files
handle index patterns with wildcard
1 parent d763ec1 commit 39728e2

File tree

3 files changed

+74
-21
lines changed

3 files changed

+74
-21
lines changed

x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/cytoscape.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ function getLayoutOptions(width: number, height: number) {
5858
rankDir: 'LR',
5959
fit: true,
6060
padding: 30,
61-
spacingFactor: 0.65,
61+
spacingFactor: 0.85,
6262
boundingBox: { x1: 0, y1: 0, w: width, h: height },
6363
};
6464
}

x-pack/plugins/ml/server/models/data_frame_analytics/analytics_manager.ts

Lines changed: 72 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,13 @@ export class AnalyticsManager {
121121
if (type === JOB_MAP_NODE_TYPES.INDEX) {
122122
// fetch index data
123123
const indexData = await this.getIndexData(id);
124-
const meta = indexData[id].mappings._meta;
125-
return { isIndexPattern: true, indexData, meta };
124+
let isWildcardIndexPattern = false;
125+
126+
if (id.includes('*')) {
127+
isWildcardIndexPattern = true;
128+
}
129+
const meta = indexData[id]?.mappings?._meta;
130+
return { isWildcardIndexPattern, isIndexPattern: true, indexData, meta };
126131
} else if (type.includes(JOB_MAP_NODE_TYPES.ANALYTICS)) {
127132
// fetch job associated with this index
128133
const jobData = await this.getAnalyticsJobData(id);
@@ -171,13 +176,38 @@ export class AnalyticsManager {
171176
return { modelElement, modelDetails: analyticsModel, edgeElement };
172177
}
173178

179+
private getIndexPatternElements(indexData: Record<string, object>, previousNodeId: string) {
180+
const result: any = { elements: [], details: {} };
181+
182+
Object.keys(indexData).forEach((indexId) => {
183+
// Create index node
184+
const nodeId = `${indexId}-${JOB_MAP_NODE_TYPES.INDEX}`;
185+
result.elements.push({
186+
data: { id: nodeId, label: indexId, type: JOB_MAP_NODE_TYPES.INDEX },
187+
});
188+
result.details[nodeId] = indexData[indexId];
189+
190+
// create edge node
191+
result.elements.push({
192+
data: {
193+
id: `${previousNodeId}~${nodeId}`,
194+
source: nodeId,
195+
target: previousNodeId,
196+
},
197+
});
198+
});
199+
200+
return result;
201+
}
202+
174203
/**
175204
* Works backward from jobId to return related jobs from source indices
176205
* @param jobId
177206
*/
178207
async getAnalyticsMap(analyticsId: string): Promise<AnalyticsMapReturnType> {
179208
const result: any = { elements: [], details: {}, error: null };
180209
const modelElements: MapElements[] = [];
210+
const indexPatternElements: MapElements[] = [];
181211

182212
try {
183213
await this.setInferenceModels();
@@ -191,17 +221,17 @@ export class AnalyticsManager {
191221
let rootTransform;
192222
let rootIndexPattern;
193223

194-
const firstNodeId = `${data.id}-${JOB_MAP_NODE_TYPES.ANALYTICS}`;
224+
let previousNodeId = `${data.id}-${JOB_MAP_NODE_TYPES.ANALYTICS}`;
195225

196226
result.elements.push({
197227
data: {
198-
id: firstNodeId,
228+
id: previousNodeId,
199229
label: data.id,
200230
type: JOB_MAP_NODE_TYPES.ANALYTICS,
201231
analysisType: getAnalysisType(data?.analysis),
202232
},
203233
});
204-
result.details[firstNodeId] = data;
234+
result.details[previousNodeId] = data;
205235

206236
let { modelElement, modelDetails, edgeElement } = this.getAnalyticsModelElements(analyticsId);
207237
if (isAnalyticsMapNodeElement(modelElement)) {
@@ -229,11 +259,33 @@ export class AnalyticsManager {
229259
}
230260
// If it's index pattern, check meta data to see what to fetch next
231261
if (isIndexPatternLinkReturnType(link) && link.isIndexPattern === true) {
232-
const nodeId = `${nextLinkId}-${JOB_MAP_NODE_TYPES.INDEX}`;
233-
result.elements.unshift({
234-
data: { id: nodeId, label: nextLinkId, type: JOB_MAP_NODE_TYPES.INDEX },
235-
});
236-
result.details[nodeId] = link.indexData;
262+
if (link.isWildcardIndexPattern === true) {
263+
// Create index nodes for each of the indices included in the index pattern then break
264+
const { details, elements } = this.getIndexPatternElements(
265+
link.indexData,
266+
previousNodeId
267+
);
268+
269+
indexPatternElements.push(...elements);
270+
result.details = { ...result.details, ...details };
271+
complete = true;
272+
} else {
273+
const nodeId = `${nextLinkId}-${JOB_MAP_NODE_TYPES.INDEX}`;
274+
result.elements.unshift({
275+
data: { id: nodeId, label: nextLinkId, type: JOB_MAP_NODE_TYPES.INDEX },
276+
});
277+
result.details[nodeId] = link.indexData;
278+
}
279+
280+
// Check meta data
281+
if (
282+
link.isWildcardIndexPattern === false &&
283+
(link.meta === undefined || link.meta?.created_by === INDEX_META_DATA_CREATED_BY)
284+
) {
285+
rootIndexPattern = nextLinkId;
286+
complete = true;
287+
break;
288+
}
237289

238290
if (link.meta?.created_by === 'data-frame-analytics') {
239291
nextLinkId = link.meta.analytics;
@@ -244,16 +296,10 @@ export class AnalyticsManager {
244296
nextLinkId = link.meta._transform?.transform;
245297
nextType = JOB_MAP_NODE_TYPES.TRANSFORM;
246298
}
247-
248-
// Check meta data
249-
if (link.meta === undefined || link.meta?.created_by === INDEX_META_DATA_CREATED_BY) {
250-
rootIndexPattern = nextLinkId;
251-
complete = true;
252-
break;
253-
}
254299
} else if (isJobDataLinkReturnType(link) && link.isJob === true) {
255300
data = link.jobData;
256301
const nodeId = `${data.id}-${JOB_MAP_NODE_TYPES.ANALYTICS}`;
302+
previousNodeId = nodeId;
257303

258304
result.elements.unshift({
259305
data: {
@@ -280,6 +326,7 @@ export class AnalyticsManager {
280326
data = link.transformData;
281327

282328
const nodeId = `${data.id}-${JOB_MAP_NODE_TYPES.TRANSFORM}`;
329+
previousNodeId = nodeId;
283330
rootTransform = data.dest.index;
284331

285332
result.elements.unshift({
@@ -296,7 +343,12 @@ export class AnalyticsManager {
296343
for (let i = 0; i < elemLength; i++) {
297344
const currentElem = result.elements[i];
298345
const nextElem = result.elements[i + 1];
299-
if (currentElem !== undefined && nextElem !== undefined) {
346+
if (
347+
currentElem !== undefined &&
348+
nextElem !== undefined &&
349+
currentElem?.data?.id.includes('*') === false &&
350+
nextElem?.data?.id.includes('*') === false
351+
) {
300352
result.elements.push({
301353
data: {
302354
id: `${currentElem.data.id}~${nextElem.data.id}`,
@@ -350,8 +402,8 @@ export class AnalyticsManager {
350402
}
351403
}
352404
}
353-
// Include model nodes in result elements now that all other nodes have been created
354-
result.elements.push(...modelElements);
405+
// Include model and index pattern nodes in result elements now that all other nodes have been created
406+
result.elements.push(...modelElements, ...indexPatternElements);
355407

356408
return result;
357409
} catch (error) {

x-pack/plugins/ml/server/models/data_frame_analytics/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
export interface IndexPatternLinkReturnType {
8+
isWildcardIndexPattern: boolean;
89
isIndexPattern: boolean;
910
indexData: any;
1011
meta: any;

0 commit comments

Comments
 (0)