Skip to content

Data Types

Data adapters assign types to extracted fields. Understanding these types helps you write correct queries and transformations.

string Text of any length
"hello", "user@example.com"
number Integers and floats
42, 3.14, -7
boolean True or false values
true, false
null Missing or undefined values
null
object Nested objects with properties
{"key": "value"}
array Arrays of mixed types
["a", "b", "c"]
regex Regular expression patterns
`^Error:.*`
TypeSyntaxExample
StringDouble quotes"hello world"
NumberBare numeric literal42, 3.14
BooleanBare keywordtrue, false
RegexBackticks`^Error:.*`
Column name with spacesSingle quotes'user name'
NullBare keywordnull

Single-quoted strings ('...') are column name references, not string values. Use them when a field name contains spaces, dots, or reserved words:

| where 'user name' == "alice"
| eval 'http.status' = status

Backtick strings are regex literals and are only valid in positions that accept a regex (e.g., match(), controller param values, regex command):

| where match(message, `^Error:.*`)
namespace=`^prod-.*`

Missing fields are represented as null. Null propagates through arithmetic and comparisons:

  • null + 5null
  • null == "x"false (not an error)
  • null == nulltrue

Use isNull() and isNotNull() in where to explicitly test for missing values:

| where isNotNull(user)
| where isNull(optional_field)

QQL does not implicitly coerce types across categories. Arithmetic on a string field produces null:

| eval result = stringField / 1000   // → null if stringField is a string

To convert types, use the appropriate eval functions (e.g., toNumber(), toString()):

| eval duration_ms = toNumber(duration_str)
| eval duration_sec = duration_ms / 1000

Adapters assign types to fields at ingestion time. The type assigned depends on the adapter and the underlying data:

  • JSON fields with numeric values become number.
  • JSON fields with true/false become boolean.
  • Everything else defaults to string.
  • Nested JSON objects become the object type and can be flattened with unpack.

When you evaluate expressions, result types depend on the operands:

| eval duration_sec = duration / 1000

If duration is a number, duration_sec is also a number. If duration is a string, duration_sec will be null.

| eval label = "status: " + status

String concatenation with + works when both sides are strings. If status is a number it will be coerced to string automatically in this context.

Comparisons are type-aware:

| where duration > 1000        // numeric comparison
| where level == "error"       // string equality
| where is_active == true      // boolean comparison
| where match(msg, `^Err`)     // regex test on string field

Comparing a string field with a number (e.g., stringField > 1000) will not match any records because the types differ.

Aggregation functions require numeric fields:

  • sum(field), avg(field), min(field), max(field) — field must be numeric; null values are ignored.
  • count() — works on any type; counts non-null records.
| stats avg(duration) by service     // duration must be numeric
| stats count() by level             // level can be any type