objectArray:eval() function iterates over
the values of a nested array (specifically, arrays of objects or
arrays of arrays), applies the function on each element, and
returns results in a new array field. Currently, the function
supports only flat arrays as the output.
Although objectArray:eval() can be used on
both flat arrays and nested arrays, then for best performance,
we recommend using objectArray:eval() only
for arrays of objects or arrays of arrays (for example parsed
JSON structures with named fields). For flat arrays, the
array:eval() function is a recommended
equivalent. For a list of functions that can be used on flat
arrays, see Array Query Functions.
| Signature | objectArray:eval(array, asArray, function, [var]) |
| Output Data | Zero or One Event per Input Event |
| Function Type | Transformation |
| Compatible Context | Query, Live Query, Aggregate Alert, Filter Alert, Legacy Alert, Parser, Non-aggregate Query |
objectArray:eval()| Parameter | Type | Interpreted Type | Required | Default Value | Description |
|---|---|---|---|---|---|
array[a] | string | string | required | ย | The array name in LogScale Array Syntax, for example, for events with fields incidents[0], incidents[1], ... this would be incidents[], as in objectArray:eval(array="incidents[]", .... |
asArray | string | string | required | value passed to the array parameter | The output array โ cannot be the same as the input array. |
function | non-aggregate function | non-aggregate function | required | ย | The function applied to each element of the array. This argument is used to write a value to the same field that is given as the output array in the asArray argument. In objectArray:eval() Examples, such a field is _mapped. |
var | string | string | optional[b] | input array name | Name of the variable to use in the function argument. |
[b] Optional parameters use their default value unless explicitly set. | |||||
Hide omitted argument names for this function
Omitted Argument NamesThe argument name for
arraycan be omitted; the following forms of this function are equivalent:logscale SyntaxobjectArray:eval("value",asArray=value passed to the array parameter,function="value")and:
logscale SyntaxobjectArray:eval(array="value",asArray=value passed to the array parameter,function="value")These examples show basic structure only.
objectArray:eval() Function Operation
When using this function:
The variable defined by the
varargument is validated to ensure it does not contain object/array access patterns, for example,[..]or..The variable becomes available as a "pseudo-field" (meaning that it's not like a proper field in the event) in the
functionargument (seeobjectArray:eval()Examples).The "pseudo-field" can access object fields within nested array entries using an array access pattern consisting of
[number]for array indexing and.for accessing object fields. These can be repeated/combined arbitrarily; for example,x.foo[0].bar.bazis a valid pattern. Use dot notation (such asx.key) to access fields in arrays of objects, and bracket notation (such asx[0][1]) for arrays of arrays.The mapping between input and output array entries is done by the
functionargument: for each input array entry,functionmaps an output array entry. The output/result value offunctionis the value of the same field (without[]) given by theasArrayargument.
objectArray:eval() Examples
Click next to an example below to get the full details.
Concatenate Multiple Values From Nested Array Elements
Concatenate multiple values from nested array elements using
objectArray:eval() function with
concat()
Query
objectArray:eval("foo[]", var=x, function={_mapped := concat([x.key.value, "x.key.others[0]", "x.key.others[1]"])}, asArray="_mapped[]")Introduction
In this example, the objectArray:eval() function is
used with the concat() function to concatenate
multiple deeply nested arrays of objects values in the array
foo[] and return the concatenated
values in the output field
_mapped[]
Example incoming data might look like this:
"foo[0].key.value": y
"foo[0].key.others[0]": 1
"foo[0].key.others[1]": 2
"foo[1].nothing": 355Step-by-Step
Starting with the source repository events.
- logscale
objectArray:eval("foo[]", var=x, function={_mapped := concat([x.key.value, "x.key.others[0]", "x.key.others[1]"])}, asArray="_mapped[]")Notice that a
varparameter can be used to give a different name to the input array variable inside the function argument. This is particularly useful whenever the input array name is very long. Event Result set.
Summary and Results
The query is used to concatenate multiple deeply nested arrays of objects values.
Sample output from the incoming example data:
_mapped[0]: y12
"foo[0].key.value": y
"foo[0].key.others[0]": 1
"foo[0].key.others[1]": 2Concatenate Values From Deeply Nested Array Elements
Concatenate deeply nested objects and arrays using
objectArray:eval() function with itself
Query
objectArray:eval(
"in[]",
asArray="out[]",
function={
objectArray:eval("in.others[]", asArray="tmp[]", function={tmp := "in.others.d"})
| out := concatArray(tmp)
}
)Introduction
In this example, the objectArray:eval() function is
used with itself to concatenate a deeply nested arrays of objects values
in the array in[] and return the
concatenated values in the output field
out[].
Example incoming data might look like this:
| in[0].others[0].d: 1 |
|---|
| in[0].others[1].d: 2 |
| in[0].others[2].d: 3 |
| in[1].others[0].d: 4 |
| in[1].others[1].d: 5 |
| in[1].others[2].d: 6 |
Step-by-Step
Starting with the source repository events.
- logscale
objectArray:eval( "in[]", asArray="out[]", function={Iterates over the array from start to end (or to the first empty index in the array, applies the given function, and returns the concatenated results in a new output array name field out[].
- logscale
objectArray:eval("in.others[]", asArray="tmp[]", function={tmp := "in.others.d"}) | out := concatArray(tmp) } )The nested
objectArray:eval()performs the concatenation of the values within the nested array by calling theconcatArray()function.Notice that in the nested call to
objectArray:eval(), the given input array name is the nested array in.others[]. This works because it is translated to the field in[i].others[] by the parentobjectArray:eval()current array indexi.To return the concatenated array, the
asArrayparameter is set to the tmp[] field, and then when we assign the value of the concatenated value. Event Result set.
Summary and Results
The query is used to concatenate deeply nested arrays of objects. The use of this function in this way is often useful when incoming ingested data has been defined in a nested structure, but needs to be displayed or summarized. For example, importing the properties or configuration values may result in a list of potential values for a given property. Concatenating the values together makes them easier to use as a summary value for display in a table or graph.
Sample output from the incoming example data:
out[0]: 123
out[1]: 456Concatenate Values From Nested Array Elements
Concatenate deeply nested objects and arrays using
objectArray:eval() function with
concat()
Query
objectArray:eval("in[]", asArray="out[]", function={out := concat(["in.a", "in.b.c", "in.others[1].d"])})Introduction
In this example, the objectArray:eval() function is
used with the concat() function to concatenate
deeply nested arrays of objects values in the array
in[] and return the concatenated
values in the output field
out[].
Example incoming data might look like this:
in[0].a: 1
in[0].b.c: 2
in[0].others[0].d: 3
in[0].others[1].d: 4Step-by-Step
Starting with the source repository events.
- logscale
objectArray:eval("in[]", asArray="out[]", function={out := concat(["in.a", "in.b.c", "in.others[1].d"])})Iterates over the array from start to end (or to the first empty index in the array), applies the given function, and returns the concatenated results in a new output array name field out[].
Event Result set.
Summary and Results
The query is used to concatenate deeply nested arrays of objects.
Sample output from the incoming example data:
out[0]: 124Concatenate Values From Two Nested Array Elements
Concatenate values from two nested array elements returning output in flat array
Query
objectArray:eval("arr[]", var=x, function={_mapped := concat([x.a, x.b])}, asArray="_mapped[]")Introduction
In this example, the objectArray:eval() function is
used with the variable x to
concatenate the values a and
b from each array element. The
concat() function is used to return the
concatenated output into a new array.
Example incoming data might look like this:
arr[0]: machine
arr[0].a: a0
arr[0].b: b0
arr[1].a: a1
arr[1].b: b1
arr[1].c: c1
arr[2].a: a2
arr[4].b: b2
other: abcStep-by-Step
Starting with the source repository events.
- logscale
objectArray:eval("arr[]", var=x, function={_mapped := concat([x.a, x.b])}, asArray="_mapped[]")Concatenates the values
aandbfrom each array element and returns the results in a new array named _mapped. In this example,objectArray:eval()iterates over each element of the array and assigns each element to the variablexwhich is then used as an alias. The new field _mapped is created by concatenating the value using the aliasxto extract each object value from each element of the array. Notice that the output in this example is a flat array.For example, this array element:
arr[0].a: a0 arr[0].b: b0 is translated to:
_mapped[0]: a0b0 Event Result set.
Summary and Results
The query is used to concatenate values of two array elements.
Sample output from the incoming example data, the original values have not been removed:
_mapped[0]: a0b0
_mapped[1]: a1b1
_mapped[2]: a2
_mapped[3]: b2
arr[0]: machine
arr[0].a: a0
arr[0].b: b0
arr[1].a: a1
arr[1].b: b1
arr[1].c: c1
arr[2].a: a2
arr[4].b: b2
other: abcCount Nested Array Elements
Count elements in nested arrays using the
objectArray:eval() function with
array:length()
Query
objectArray:eval(array="arrayToCount[]", asArray="tmpCountArray[]", function={ tmpCountArray:=true })
| array:length("tmpCountArray[]")
| array:drop("tmpCountArray[]")Introduction
In this example, the objectArray:eval() function is
used to iterate over a nested array field named
arrayToCount[] and populate a temporary flat array
named tmpCountArray[] with a marker value of
true for each element. This enables
array:length() to count the number of elements in
the array of objects, which it otherwise cannot do directly.
Example incoming data might look like this:
| @rawstring | @timestamp | @timestamp.nanos | arrayToCount[0].name | arrayToCount[0].value | arrayToCount[1].name | arrayToCount[1].value | arrayToCount[2].name | arrayToCount[2].value | arrayToCount[3].name | arrayToCount[3].value | host |
|---|---|---|---|---|---|---|---|---|---|---|---|
| "arrayToCount[0].name"=alpha "arrayToCount[0].value"=10 "arrayToCount[1].name"=beta "arrayToCount[1].value"=20 "arrayToCount[2].name"=gamma "arrayToCount[2].value"=30 host="server-01" | 1774950025788 | 0 | alpha | 10 | beta | 20 | gamma | 30 | <no value> | <no value> | server-01 |
| "arrayToCount[0].name"=delta "arrayToCount[0].value"=5 "arrayToCount[1].name"=epsilon "arrayToCount[1].value"=15 "arrayToCount[2].name"=zeta "arrayToCount[2].value"=25 "arrayToCount[3].name"=eta "arrayToCount[3].value"=35 host="server-02" | 1774950025788 | 0 | delta | 5 | epsilon | 15 | zeta | 25 | eta | 35 | server-02 |
| "arrayToCount[0].name"=theta "arrayToCount[0].value"=100 "arrayToCount[1].name"=iota "arrayToCount[1].value"=200 host="server-03" | 1774950025788 | 0 | theta | 100 | iota | 200 | <no value> | <no value> | <no value> | <no value> | server-03 |
| "arrayToCount[0].name"=kappa "arrayToCount[0].value"=7 host="server-04" | 1774950025788 | 0 | kappa | 7 | <no value> | <no value> | <no value> | <no value> | <no value> | <no value> | server-04 |
| "arrayToCount[0].name"=lambda "arrayToCount[0].value"=42 "arrayToCount[1].name"=mu "arrayToCount[1].value"=84 "arrayToCount[2].name"=nu "arrayToCount[2].value"=126 "arrayToCount[3].name"=xi "arrayToCount[3].value"=168 host="server-05" | 1774950025788 | 0 | lambda | 42 | mu | 84 | nu | 126 | xi | 168 | server-05 |
| "arrayToCount[0].name"=omicron "arrayToCount[0].value"=3 "arrayToCount[1].name"=pi "arrayToCount[1].value"=6 "arrayToCount[2].name"=rho "arrayToCount[2].value"=9 host="server-06" | 1774950025788 | 0 | omicron | 3 | pi | 6 | rho | 9 | <no value> | <no value> | server-06 |
| "arrayToCount[0].name"=sigma "arrayToCount[0].value"=11 "arrayToCount[1].name"=tau "arrayToCount[1].value"=22 host="server-07" | 1774950025788 | 0 | sigma | 11 | tau | 22 | <no value> | <no value> | <no value> | <no value> | server-07 |
| "arrayToCount[0].name"=upsilon "arrayToCount[0].value"=55 "arrayToCount[1].name"=phi "arrayToCount[1].value"=110 "arrayToCount[2].name"=chi "arrayToCount[2].value"=165 "arrayToCount[3].name"=psi "arrayToCount[3].value"=220 host="server-08" | 1774950025788 | 0 | upsilon | 55 | phi | 110 | chi | 165 | psi | 220 | server-08 |
Each event contains a nested array field
arrayToCount[], where each element is an object
with sub-fields such as arrayToCount[n].name and
arrayToCount[n].value. Because the array elements
are objects rather than scalar values,
array:length() alone cannot count them. The
workaround described in this example resolves this limitation.
Step-by-Step
Starting with the source repository events.
- logscale
objectArray:eval(array="arrayToCount[]", asArray="tmpCountArray[]", function={ tmpCountArray:=true })The
objectArray:eval()function iterates over each element of the array of objects specified by thearrayparameter, here set to arrayToCount[].For each element found, it evaluates the expression provided in the
functionparameter โ in this case assigning the valuetrueto a field named tmpCountArray, which will be an element of the output array. Note that the field name must match the array name specified in theasArrayparameter.The results are collected into a new flat array specified by the
asArrayparameter, named tmpCountArray[].After this step, tmpCountArray[] contains one entry of
trueper element in the original nested array arrayToCount[], effectively creating a flat, countable representation of the nested array's length. Without this intermediate step,array:length()would be unable to count the elements because it does not operate on object-type (nested) arrays.Note that the temporary array (in this example tmpCountArray[]) must have a unique name for each searched event. If the name is not unique, LogScale overwrites and drops existing fields from the event.
- logscale
| array:length("tmpCountArray[]")The
array:length()function counts the number of elements in the flat array tmpCountArray[] that was created in the previous step. Because tmpCountArray[] is a flat array with onetrueentry per original nested element, this count accurately reflects the number of elements in the original nested array arrayToCount[]. The function returns the result in a new field named _length by default. - logscale
| array:drop("tmpCountArray[]")Removes the temporary flat array tmpCountArray[] from the event. Since this array was only created as an intermediate step to enable counting, it is no longer needed once
array:length()has returned the count in the _length field. Dropping it keeps the output clean and avoids polluting the results with intermediate fields. Event Result set.
Summary and Results
The query is used to count the number of elements in a nested object
array field by using the objectArray:eval()
function to create a temporary flat array of marker values, then
applying the array:length() function to find the
length of the flat temporary array, and finally removing the temporary
array with array:drop().
This query is useful, for example, to determine how many sub-objects are
present in a nested array field per event โ such as counting the
number of items in a shopping cart, the number of network interfaces on
a host, or the number of findings in a security alert โ in cases
where the array:length() function alone cannot
operate on object arrays.
Sample output from the incoming example data:
| _length | arrayToCount[0].name | arrayToCount[0].value | arrayToCount[1].name | arrayToCount[1].value | arrayToCount[2].name | arrayToCount[2].value | arrayToCount[3].name | arrayToCount[3].value | host |
|---|---|---|---|---|---|---|---|---|---|
| 3 | alpha | 10 | beta | 20 | gamma | 30 | <no value> | <no value> | server-01 |
| 4 | delta | 5 | epsilon | 15 | zeta | 25 | eta | 35 | server-02 |
| 2 | theta | 100 | iota | 200 | <no value> | <no value> | <no value> | <no value> | server-03 |
| 1 | kappa | 7 | <no value> | <no value> | <no value> | <no value> | <no value> | <no value> | server-04 |
| 4 | lambda | 42 | mu | 84 | nu | 126 | xi | 168 | server-05 |
| 3 | omicron | 3 | pi | 6 | rho | 9 | <no value> | <no value> | server-06 |
| 2 | sigma | 11 | tau | 22 | <no value> | <no value> | <no value> | <no value> | server-07 |
| 4 | upsilon | 55 | phi | 110 | chi | 165 | psi | 220 | server-08 |
Note that the original nested array fields
arrayToCount[] are still present in the output
alongside host and _length
โ only the intermediate tmpCountArray[] field
has been removed by array:drop().
Also note that the count in _length reflects only
the number of populated elements in the nested array per event, so
events with fewer sub-objects will return a lower count accordingly, as
seen with server-04 which contains only a single
nested array element and therefore returns a
_length value of 1.
Create Single Array from Object Arrays
Transform one or more objects from object arrays into a single array
Query
"a[0].foo" := "a"
| "a[0].bar" := "b"
| "a[1].foo" := "c"
| "a[1].bar" := "d"
| objectArray:eval(array="a[]", asArray="output[]", var="x", function={output := x.bar})Introduction
In this example, the objectArray:eval() function is
used to extract one object from each element of an array of objects into
a new array.
Example incoming data might look like this:
| a[0].foo: a |
|---|
| a[0].bar: b |
| a[1].foo: c |
| a[1].bar: d |
Step-by-Step
Starting with the source repository events.
- logscale
"a[0].foo" := "a" | "a[0].bar" := "b" | "a[1].foo" := "c" | "a[1].bar" := "d" - logscale
| objectArray:eval(array="a[]", asArray="output[]", var="x", function={output := x.bar})Iterates (creates a loop) over the array
a[]and adds the value of the object.barto a new arrayoutput[]. This is achieved by executing an anonymous function, which sets the value ofoutputto the iterated value ofx.barfroma[].The
asArrayparameter is set to the output[] field, creating an array where each element contains the value of x.bar from the corresponding iteration. Event Result set.
Summary and Results
The query is used to create an array from compound arrays. This can be useful when you need to collect specific values from nested arrays for further processing, filtering, or analysis.
Sample output from the incoming example data:
| a[0].foo | a[0].bar | a[1].foo | a[1].bar | output[0] | output[1] |
|---|---|---|---|---|---|
| a | b | c | d | b | d |