Docs
DocumentationQuery ReferenceAPI Reference
Open Console→→
DocumentationQuery ReferenceAPI Reference

Introduction

Query reference overview

APL

IntroductionSample queriesAll features
Functions
Scalar functions
Array functions
Overview
array_concat
array_extract
array_iff
array_index_of
array_length
array_reverse
array_rotate_left
array_rotate_right
array_select_dict
array_shift_left
array_shift_right
array_slice
array_sort_asc
array_sort_desc
array_split
array_sum
bag_has_key
bag_keys
bag_pack
bag_zip
isarray
len
pack_array
pack_dictionary
strcat_array
Conditional functions
Overview
case
iff
Conversion functions
Overview
dynamic_to_json
ensure_field
isbool
toarray
tobool
todatetime
todouble, toreal
todynamic
tohex
toint, tolong
tostring
totimespan
Datetime functions
Overview
ago
datetime_add
datetime_diff
datetime_part
dayofmonth
dayofweek
dayofyear
endofday
endofmonth
endofweek
endofyear
getmonth
getyear
hourofday
monthofyear
now
startofday
startofmonth
startofweek
startofyear
unixtime_microseconds_todatetime
unixtime_milliseconds_todatetime
unixtime_nanoseconds_todatetime
unixtime_seconds_todatetime
week_of_year
GenAI functions
Overview
genai_concat_contents
genai_conversation_turns
genai_cost
genai_estimate_tokens
genai_extract_assistant_response
genai_extract_function_results
genai_extract_system_prompt
genai_extract_tool_calls
genai_extract_user_prompt
genai_get_content_by_index
genai_get_content_by_role
genai_get_pricing
genai_get_role
genai_has_tool_calls
genai_input_cost
genai_is_truncated
genai_message_roles
genai_output_cost
Hash functions
Overview
hash
hash_md5
hash_sha1
hash_sha256
hash_sha512
IP functions
Overview
format_ipv4
format_ipv4_mask
geo_info_from_ip_address
has_any_ipv4
has_any_ipv4_prefix
has_ipv4
has_ipv4_prefix
ipv4_compare
ipv4_is_in_range
ipv4_is_in_any_range
ipv4_is_match
ipv4_is_private
ipv4_netmask_suffix
ipv6_compare
ipv6_is_in_any_range
ipv6_is_in_range
ipv6_is_match
parse_ipv4
parse_ipv4_mask
Mathematical functions
Overview
abs
acos
asin
atan
atan2
cos
cot
degrees
exp
exp2
exp10
gamma
isfinite
isinf
isint
isnan
log
log2
log10
loggamma
max_of
min_of
not
pi
pow
radians
rand
range
round
set_difference
set_has_element
set_intersect
set_union
sign
sin
sqrt
tan
Metadata functions
Overview
column_ifexists
cursor_current
ingestion_time
Pair functions
Overview
find_pair
pair
parse_pair
Rounding functions
Overview
bin
bin_auto
ceiling
floor
String functions
Overview
base64_decode_toarray
base64_decode_tostring
base64_encode_fromarray
base64_encode_tostring
coalesce
countof
countof_regex
extract
extract_all
format_bytes
format_url
gettype
indexof
indexof_regex
isascii
isempty
isnotempty
isnotnull
isnull
parse_bytes
parse_csv
parse_json
parse_path
parse_url
parse_urlquery
quote
regex_quote
replace
replace_regex
replace_string
reverse
split
strcat
strcat_delim
strcmp
string_size
strlen
strrep
strip_ansi_escapes
substring
tolower
totitle
toupper
translate
trim
trim_end
trim_end_regex
trim_regex
trim_space
trim_start
trim_start_regex
unicode_codepoints_from_string
unicode_codepoints_to_string
url_decode
url_encode
SQL functions
Overview
parse_sql
format_sql
Time series functions
Overview
series_abs
series_acos
series_add
series_asin
series_atan
series_ceiling
series_cos
series_cosine_similarity
series_divide
series_dot_product
series_equals
series_exp
series_fft
series_fill_backward
series_fill_const
series_fill_forward
series_fill_linear
series_fir
series_floor
series_greater
series_greater_equals
series_ifft
series_iir
series_less
series_less_equals
series_log
series_magnitude
series_max
series_min
series_multiply
series_not_equals
series_pearson_correlation
series_pow
series_sign
series_sin
series_stats
series_stats_dynamic
series_subtract
series_sum
series_tan
Type functions
Overview
isimei
ismap
isreal
iscc
isstring
isutf8
Aggregation functions
Overview
arg_min
arg_max
avg
avgif
count
countif
dcount
dcountif
histogram
histogramif
make_list
make_list_if
make_set
make_set_if
max
maxif
min
minif
percentile
percentileif
percentiles_array
percentiles_arrayif
phrases
rate
spotlight
stdev
stdevif
sum
sumif
topk
topkif
variance
varianceif
Operators
Tabular operators
Overview
count
distinct
extend
extend-valid
externaldata
getschema
join
limit
lookup
make-series
mv-expand
order
parse
parse-kv
parse-where
project
project-away
project-keep
project-rename
project-reorder
redact
sample
search
sort
summarize
take
top
union
where
Scalar operators
Set membership operators
Overview
in
!in
in~
!in~
Logical
Numerical
String
Reference
Entity names
Map fields
Null values
Scalar data types
Set statement
Special field attributes
Migrate
Splunk SPL
SQL
Sumo Logic

MPL

Language featuresHistograms and summariesSample queriesMigrate
APL/Reference

Map fields

This page explains what map fields are and how to query them.

Map fields are a special type of field that can hold a collection of nested key-value pairs within a single field. You can think of the content of a map field as a JSON object.

Axiom automatically creates map fields in datasets that use OpenTelemetry and you can create map fields yourself in any dataset.

Benefits and drawbacks of map fields

Map fields help you manage high-dimensionality data by storing multiple key-value pairs within a single field. One of the benefits of map fields is that you can store additional attributes without adding more fields. This is particularly useful when the shape of your data is unpredictable (for example, additional attributes added by OpenTelemetry instrumentation). Using map fields means that you can avoid reaching the field limit of a dataset.

Use map fields in the following cases:

  • You approach the dataset field limit.
  • The shape of your data is unpredictable. For example, an OpenTelemetry instrumentation or another SDK creates objects with many keys.
  • You work with feature flags or custom attributes that generate many fields.

Map fields reduce impact on field limits, but involve trade-offs in query efficiency and compression. The drawbacks of map fields are the following:

  • Querying map fields uses more query-hours than querying conventional fields.
  • In some cases, map fields don’t compress as well as conventional fields. For example, if there is little shared structure between map values. This means datasets with map fields can use more storage.
  • You don’t have visibility into map fields from the schema. For example, autocomplete doesn’t know the properties inside the map field.

Custom attributes in tracing datasets

If you use OpenTelemetry to send data to Axiom, you find some attributes in the attributes.custom map field. The reason is that instrumentation libraries can add hundreds or even thousands of arbitrary attributes to spans. Storing each custom attribute in a separate field would significantly increase the number of fields in your dataset. To keep the number of fields in your dataset under control, Axiom places all custom attributes in the single attributes.custom map field.

Use map fields in queries

Map fields are particularly useful for handling nested data structures, such as data from logfmt format or other key-value formats with unpredictable structure.

The example query below uses the http.protocol property inside the attributes.custom map field to filter results:

APLRun in Playground
['otel-demo-traces']
| where ['attributes.custom']['http.protocol'] == 'HTTP/1.1'

Create map fields using UI

To create a map field using the UI:

  1. Go to the Datasets tab.
  2. Select the dataset where you want to create the map field.
  3. In the top right of the fields list, click More > Create map field.
  4. In Field name, enter the full name of the field, including parent fields, if any. For example, map_field_name. For more information on syntax, see Access properties of nested maps
  5. Click Create map field.

Create map fields using API

To create a map field using the Axiom API, send a request to the Create map field endpoint. For example:

shell
curl --request POST \
  --url https://api.axiom.co/v2/datasets/DATASET_NAME/mapfields \
  --header 'Authorization: Bearer API_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "MAP_FIELD"
}'
Info

Replace API_TOKEN with the Axiom API token you have generated. For added security, store the API token in an environment variable.

Replace DATASET_NAME with the name of the Axiom dataset where you send your data.

Replace MAP_FIELD with the name of the field that you want to change to a map field.

Info

Creating a map field affects the schema of the dataset. If the dataset’s schema is locked, Axiom automatically regenerates the locked schema when you create a map field so that the locked schema reflects the change. For more information, see Lock dataset schema.

View map fields

To view map fields:

  1. Go to the Datasets tab.
  2. Select a dataset where you want to view map fields.
  3. Map fields are labelled in the following way:
  • MAPPED means that the field was previously an ordinary field but at some point its parent was changed to a map field. Axiom adds new events to the field as an attribute of the parent map field. Events you ingested before the change retain the ordinary structure. To remove the ordinary field together with the values you ingested before the change, delete the field. This doesn’t affect the values that Axiom stores in the parent map field.
  • UNUSED means that the field is configured as a map field but you haven’t yet ingested data into it. Once ingested, data within this field won’t count toward your field limit.
  • REMOVED means that the field was configured as a map field but at some point it was changed to an ordinary field. Axiom adds new events to the field as usual. Events you ingested before the change retain the map structure. To fully remove this field, delete the field. Alternatively, trim your dataset to remove the time period when map data was ingested, and then vacuum the fields.

Access properties of nested maps

To access the properties of nested maps, use index notation, dot notation, or a mix of the two. If you use index notation for an entity, enclose the entity name in quotation marks (' or ") and square brackets ([]). For example:

  • where ['map_field']['property1']['property2'] == 14
  • where map_field.property1.property2 == 14
  • where ['map_field'].property1.property2 == 14

If an entity name has spaces ( ), dots (.), or dashes (-), you can only use index notation for that entity. You can use dot notation for the other entities. For example:

  • where ['map.field']['property.name1']['property.name2'] == 14
  • where ['map.field'].property1.property2 == 14
Info

In OTel traces, custom attributes are located in the attributes.custom map field. You can access them as ['attributes.custom']['header.Accept'], for example. In this case, you don’t access the Accept field nested within the header field. What actually happens is that you access the field named header.Accept within the attributes.custom map field.

For more information on quoting field names, see Entity names.

Map fields and flattened fields

Within a dataset, the same fields can exist as flattened fields and as subfields of a map field.

For example, consider the following:

  1. geo is initially not a map field.

  2. You ingest the following:

    JSON
    {
      "geo": {
        "city": "Paris",
        "country": "France"
      }
    }

    This adds two flattened fields to the dataset that you can access as ['geo.city'] or ['geo.country'].

  3. You change geo to a map field through the UI or the API.

  4. You ingest the following:

    JSON
    {
      "geo": {
        "city": "Paris",
        "country": "France"
      }
    }

    You use the same ingest JSON as before, but this adds the new subfields to the geo parent map field. You can access the subfields as ['geo']['city'] and ['geo']['country'].

Axiom treats the flattened fields (['geo.city'] and ['geo.country']) and the subfields of the map field (['geo']['city'] and ['geo']['country']) as separate fields and doesn’t maintain a relationship between them.

Info

Queries using ['geo.city'] access a field literally named geo.city, while ['geo']['city'] accesses the city key inside a geo map. These references aren’t equivalent.

To avoid confusion:

  • Choose either a flattened or map-based structure when designing your schema.
  • Be explicit in queries about which fields to include or exclude.
Was this page helpful?
Suggest edits on GitHub
PreviousEntity namesNextNull values
On this page
Benefits and drawbacks of map fieldsCustom attributes in tracing datasetsUse map fields in queriesCreate map fields using UICreate map fields using APIView map fieldsAccess properties of nested mapsMap fields and flattened fields