Multi-value Fields

Each metadata field commonly stores only one value, e.g. one integer, one string, one date, etc. However, you can also set one field to carry more values of the same type.

Example 8. Example situations when you could take advantage of multivalue fields

  • A record containing an employee’s ID, Name and Address. Since employees move from time to time, you might need to keep track of all their addresses, both current and past. Instead of creating new metadata fields each time an employee moves to a new address, you can store a list of all addresses into one field.

  • You are processing an input stream of CSV files, each containing a different column count. Normally, that would imply creating new metadata for each file (each column count). Instead, you can define a generic map or variant in metadata and append fields to it each time they occur.

As implied above, there are three types of structures:

list - is a set containing elements of a given data type (any you want). In source code, lists are marked by the [] brackets, for example:

integer[] list1 = [1, 367, -1, 20, 5, 0, -79]; // a list of integer elements
boolean[] list2 = [true, false, randomBoolean()]; // a list of three boolean elements
string[] list3; // a just-declared empty list to be filled by strings

map - is a pair of keys and their values. A key is always a string while a value can be any data type - but you cannot mix them (remember a map holds values of the same type). Example:

map[string, date] dateMap; // declaration

// filling the map with values
dateMap["a"] = 2011-01-01;
dateMap["b"] = 2012-12-31;
dateMap["c"] = randomDate(2011-01-01,2012-12-31);

variant - can contain any data type or complex data structure including list or map.

variant myVariant = {}; // declaration, variant containing empty map
integer[] ordersList = [1, 15, 63]; // declaration, list of integers

// filling the variant with values
myVariant["name"] = "John Doe";
myVariant["dateOfBirth"] = 2012-12-31;
myVariant["isCustomer"] = true;
myVariant["orderIds"] = ordersList;

For more information about maps, lists and variants, see Data Types in CTL2.


Hint!


To change a field from single-value to list/map:

  1. Go to Metadata Editor.
  2. Click a field or create a new one.
  3. In Property > Basic, switch Container Type either to list or map. (You will see an icon appears next to the field Type in the left hand record pane.)

Lists and Maps Support in Components

An alphabetically sorted list of components which you can use multivalue fields in:

COMPONENTLISTMAPVARIANTNOTE
Concatenateβœ“βœ“βœ“
DataGeneratorβœ“βœ“βœ“
DataIntersectionβœ“xβœ“Map/Variant is not a part of key
DBJoinβœ“xx
DBJoinβœ“βœ“βœ“Map/Variant is not a part of key
Dedupβœ“xxSorted input
Dedupβœ“xβœ“Unsorted input
Dedupβœ“[extβœ“βœ“Map is not a part of key
Denormalizerβœ“xx
Denormalizerβœ“βœ“βœ“Map/Variant is not a part of key
ExtHashJoinβœ“xβœ“
ExtHashJoinβœ“βœ“βœ“Map is not a part of key
ExtMergeJoinβœ“xx
ExtMergeJoinβœ“βœ“βœ“Map/Variant is not a part of key
ExtSortβœ“xx
ExtSortβœ“βœ“βœ“Map/Variant is not a part of key
Filterβœ“βœ“βœ“
JSONExtractβœ“xβœ“
JSONReaderβœ“xx
JSONWriterβœ“xβœ“
LookupJoinβœ“βœ“βœ“
LookupTableReaderWriterβœ“βœ“βœ“
Mergeβœ“xx
Mergeβœ“βœ“βœ“Map/Variant not a part of key
Normalizerβœ“βœ“βœ“
Mapβœ“βœ“βœ“
RelationalJoinβœ“xx
RelationalJoinβœ“βœ“βœ“Map/Variant is not a part of key
Rollupβœ“xxSorted input
Rollupβœ“xβœ“Unsorted input
Rollupβœ“βœ“βœ“Map is not a part of key
SimpleCopyβœ“βœ“βœ“
SimpleGatherβœ“βœ“βœ“
SortWithinGroupsβœ“xx
SortWithinGroupsβœ“βœ“βœ“Map/Variant is not a part of key
XMLExtractβœ“xx
XMLReaderβœ“xx
XMLWriterβœ“βœ“x

At the moment, map, list and variant structures cannot be extracted as metadata from flat files.

Joining on multivalue fields (Comparison Rules)

You can specify fields that are lists, maps or variants as Join keys (see Join Types) just like any other fields. The only question is when two fields are equal.

A list/map/variant can:

  • be null - its value is not specified;
map[string, date] myMap; // a just-declared map - no keys, no values
  • contain empty elements
string[] myList = ["hello", ""]; // a list whose second element is empty
variant singleValue = "hello"; // variant containing string
variant multiValue = ["hello", "world"]; // variant containing list of strings

Two maps/lists/variants are equal if both of them are not null, they have the same data type, element count and all element values (keys-values in maps) are equal.

Two maps/lists/variants are not equal if either of them is null.

Warning!

When comparing two lists, the order of their elements has to match, too. In maps and variants, there is no 'order' of elements, therefore you cannot use them in Sort key.

Example 9. Integer lists which are (not) equal - symbolic notation

[1,2] == [1,2]
[null] != [1,2]
[1] != [1,2]
null != null // two unspecified lists
[null] == [null] // an extra case: lists which are not empty but whose elements are null