@@ -298,6 +298,124 @@ function _generateMappings(
298298 }
299299 }
300300
301+ function addObjectAsDynamicMapping ( field : Field ) {
302+ const path = ctx . groupFieldName ? `${ ctx . groupFieldName } .${ field . name } ` : field . name ;
303+ const pathMatch = path . includes ( '*' ) ? path : `${ path } .*` ;
304+
305+ let dynProperties : Properties = getDefaultProperties ( field ) ;
306+ let matchingType : string | undefined ;
307+ switch ( field . object_type ) {
308+ case 'histogram' :
309+ dynProperties = histogram ( field ) ;
310+ matchingType = field . object_type_mapping_type ?? '*' ;
311+ break ;
312+ case 'ip' :
313+ case 'keyword' :
314+ case 'match_only_text' :
315+ case 'text' :
316+ case 'wildcard' :
317+ dynProperties . type = field . object_type ;
318+ matchingType = field . object_type_mapping_type ?? 'string' ;
319+ break ;
320+ case 'scaled_float' :
321+ dynProperties = scaledFloat ( field ) ;
322+ matchingType = field . object_type_mapping_type ?? '*' ;
323+ break ;
324+ case 'aggregate_metric_double' :
325+ dynProperties . type = field . object_type ;
326+ dynProperties . metrics = field . metrics ;
327+ dynProperties . default_metric = field . default_metric ;
328+ matchingType = field . object_type_mapping_type ?? '*' ;
329+ break ;
330+ case 'double' :
331+ case 'float' :
332+ case 'half_float' :
333+ dynProperties . type = field . object_type ;
334+ if ( isIndexModeTimeSeries ) {
335+ dynProperties . time_series_metric = field . metric_type ;
336+ }
337+ matchingType = field . object_type_mapping_type ?? 'double' ;
338+ break ;
339+ case 'byte' :
340+ case 'long' :
341+ case 'short' :
342+ case 'unsigned_long' :
343+ dynProperties . type = field . object_type ;
344+ if ( isIndexModeTimeSeries ) {
345+ dynProperties . time_series_metric = field . metric_type ;
346+ }
347+ matchingType = field . object_type_mapping_type ?? 'long' ;
348+ break ;
349+ case 'integer' :
350+ // Map integers as long, as in other cases.
351+ dynProperties . type = 'long' ;
352+ if ( isIndexModeTimeSeries ) {
353+ dynProperties . time_series_metric = field . metric_type ;
354+ }
355+ matchingType = field . object_type_mapping_type ?? 'long' ;
356+ break ;
357+ case 'boolean' :
358+ dynProperties . type = field . object_type ;
359+ if ( isIndexModeTimeSeries ) {
360+ dynProperties . time_series_metric = field . metric_type ;
361+ }
362+ matchingType = field . object_type_mapping_type ?? field . object_type ;
363+ break ;
364+ case 'group' :
365+ if ( ! field ?. fields ) {
366+ break ;
367+ }
368+ const subFields = field . fields . map ( ( subField ) => ( {
369+ ...subField ,
370+ type : 'object' ,
371+ object_type : subField . object_type ?? subField . type ,
372+ } ) ) ;
373+ const mappings = _generateMappings (
374+ subFields ,
375+ {
376+ ...ctx ,
377+ groupFieldName : ctx . groupFieldName ? `${ ctx . groupFieldName } .${ field . name } ` : field . name ,
378+ } ,
379+ isIndexModeTimeSeries
380+ ) ;
381+ if ( mappings . hasDynamicTemplateMappings ) {
382+ hasDynamicTemplateMappings = true ;
383+ }
384+ break ;
385+ case 'flattened' :
386+ dynProperties . type = field . object_type ;
387+ matchingType = field . object_type_mapping_type ?? 'object' ;
388+ break ;
389+ default :
390+ throw new PackageInvalidArchiveError (
391+ `No dynamic mapping generated for field ${ path } of type ${ field . object_type } `
392+ ) ;
393+ }
394+
395+ if ( field . dimension && isIndexModeTimeSeries ) {
396+ dynProperties . time_series_dimension = field . dimension ;
397+ }
398+
399+ // When a wildcard field specifies the subobjects setting,
400+ // the parent intermediate object should set the subobjects
401+ // setting.
402+ //
403+ // For example, if a wildcard field `foo.*` has subobjects,
404+ // we should set subobjects on the intermediate object `foo`.
405+ //
406+ if ( field . subobjects !== undefined && path . includes ( '*' ) ) {
407+ subobjects = field . subobjects ;
408+ }
409+
410+ if ( dynProperties && matchingType ) {
411+ addDynamicMappingWithIntermediateObjects ( path , pathMatch , matchingType , dynProperties ) ;
412+
413+ // Add the parent object as static property, this is needed for
414+ // index templates not using `"dynamic": true`.
415+ addParentObjectAsStaticProperty ( field ) ;
416+ }
417+ }
418+
301419 // TODO: this can happen when the fields property in fields.yml is present but empty
302420 // Maybe validation should be moved to fields/field.ts
303421 if ( fields ) {
@@ -359,123 +477,7 @@ function _generateMappings(
359477 }
360478
361479 if ( type === 'object' && field . object_type ) {
362- const path = ctx . groupFieldName ? `${ ctx . groupFieldName } .${ field . name } ` : field . name ;
363- const pathMatch = path . includes ( '*' ) ? path : `${ path } .*` ;
364-
365- let dynProperties : Properties = getDefaultProperties ( field ) ;
366- let matchingType : string | undefined ;
367- switch ( field . object_type ) {
368- case 'histogram' :
369- dynProperties = histogram ( field ) ;
370- matchingType = field . object_type_mapping_type ?? '*' ;
371- break ;
372- case 'ip' :
373- case 'keyword' :
374- case 'match_only_text' :
375- case 'text' :
376- case 'wildcard' :
377- dynProperties . type = field . object_type ;
378- matchingType = field . object_type_mapping_type ?? 'string' ;
379- break ;
380- case 'scaled_float' :
381- dynProperties = scaledFloat ( field ) ;
382- matchingType = field . object_type_mapping_type ?? '*' ;
383- break ;
384- case 'aggregate_metric_double' :
385- dynProperties . type = field . object_type ;
386- dynProperties . metrics = field . metrics ;
387- dynProperties . default_metric = field . default_metric ;
388- matchingType = field . object_type_mapping_type ?? '*' ;
389- break ;
390- case 'double' :
391- case 'float' :
392- case 'half_float' :
393- dynProperties . type = field . object_type ;
394- if ( isIndexModeTimeSeries ) {
395- dynProperties . time_series_metric = field . metric_type ;
396- }
397- matchingType = field . object_type_mapping_type ?? 'double' ;
398- break ;
399- case 'byte' :
400- case 'long' :
401- case 'short' :
402- case 'unsigned_long' :
403- dynProperties . type = field . object_type ;
404- if ( isIndexModeTimeSeries ) {
405- dynProperties . time_series_metric = field . metric_type ;
406- }
407- matchingType = field . object_type_mapping_type ?? 'long' ;
408- break ;
409- case 'integer' :
410- // Map integers as long, as in other cases.
411- dynProperties . type = 'long' ;
412- if ( isIndexModeTimeSeries ) {
413- dynProperties . time_series_metric = field . metric_type ;
414- }
415- matchingType = field . object_type_mapping_type ?? 'long' ;
416- break ;
417- case 'boolean' :
418- dynProperties . type = field . object_type ;
419- if ( isIndexModeTimeSeries ) {
420- dynProperties . time_series_metric = field . metric_type ;
421- }
422- matchingType = field . object_type_mapping_type ?? field . object_type ;
423- break ;
424- case 'group' :
425- if ( ! field ?. fields ) {
426- break ;
427- }
428- const subFields = field . fields . map ( ( subField ) => ( {
429- ...subField ,
430- type : 'object' ,
431- object_type : subField . object_type ?? subField . type ,
432- } ) ) ;
433- const mappings = _generateMappings (
434- subFields ,
435- {
436- ...ctx ,
437- groupFieldName : ctx . groupFieldName
438- ? `${ ctx . groupFieldName } .${ field . name } `
439- : field . name ,
440- } ,
441- isIndexModeTimeSeries
442- ) ;
443- if ( mappings . hasDynamicTemplateMappings ) {
444- hasDynamicTemplateMappings = true ;
445- }
446- break ;
447- case 'flattened' :
448- dynProperties . type = field . object_type ;
449- matchingType = field . object_type_mapping_type ?? 'object' ;
450- break ;
451- default :
452- throw new PackageInvalidArchiveError (
453- `No dynamic mapping generated for field ${ path } of type ${ field . object_type } `
454- ) ;
455- }
456-
457- if ( field . dimension && isIndexModeTimeSeries ) {
458- dynProperties . time_series_dimension = field . dimension ;
459- }
460-
461- // When a wildcard field specifies the subobjects setting,
462- // the parent intermediate object should set the subobjects
463- // setting.
464- //
465- // For example, if a wildcard field `foo.*` has subobjects,
466- // we should set subobjects on the intermediate object `foo`.
467- //
468- if ( field . subobjects !== undefined && path . includes ( '*' ) ) {
469- subobjects = field . subobjects ;
470- }
471-
472- if ( dynProperties && matchingType ) {
473- addDynamicMappingWithIntermediateObjects ( path , pathMatch , matchingType , dynProperties ) ;
474-
475- // Add the parent object as static property, this is needed for
476- // index templates not using `"dynamic": true`.
477- addParentObjectAsStaticProperty ( field ) ;
478- }
480+ addObjectAsDynamicMapping ( field ) ;
479481 } else {
480482 let fieldProps = getDefaultProperties ( field ) ;
481483
@@ -491,6 +493,12 @@ function _generateMappings(
491493 } ,
492494 isIndexModeTimeSeries
493495 ) ;
496+ if ( field . object_type ) {
497+ // A group can have an object_type if it has been merged with an object during deduplication,
498+ // generate also the dynamic mapping for the object.
499+ addObjectAsDynamicMapping ( field ) ;
500+ mappings . hasDynamicTemplateMappings = true ;
501+ }
494502 if ( mappings . hasNonDynamicTemplateMappings ) {
495503 fieldProps = {
496504 properties :
0 commit comments