Arctic Wolf Query Language (AQL)
The Arctic Wolf Query Language (AQL) is a pipe-based query language for building advanced telemetry queries in Data Explorer.
AQL syntax basics
AQL queries are built as a pipeline of stages separated by the pipe character (|). Each stage transforms the result of the previous stage.
AQL uses two naming conventions consistently across operators:
| Convention | Meaning | Example |
|---|---|---|
! prefix |
Negates the operator (returns the opposite rows) | contains → !contains |
~ suffix |
Case-insensitive variant of the base operator | contains → contains~ |
! + ~ |
Negated and case-insensitive | !contains~ |
For most operator families, four variants exist: the base form, its negation, its case-insensitive form, and the negated case-insensitive form. For example, has, !has, has~, !has~.
Equality and relational operators
These operators compare scalar values such as numbers, strings, dates, and booleans.
| Operator | Name | Description | Example |
|---|---|---|---|
== |
Equal | Field value exactly matches the given value (case-sensitive for strings). | severity == "High" |
!= |
Not equal | Field value does not match the given value. | status != "Closed" |
< |
Less than | Field value is strictly less than the given value. | age < 18 |
<= |
Less than or equal | Field value is less than or equal to the given value. | age <= 18 |
> |
Greater than | Field value is strictly greater than the given value. | score > 90 |
>= |
Greater than or equal | Field value is greater than or equal to the given value. | age >= 18 |
=~ |
Equal (case-insensitive) | Case-insensitive version of ==. For example, status =~ "open" matches "Open" and "OPEN". |
name =~ "arctic wolf" |
!~ |
Not equal (case-insensitive) | Case-insensitive version of !=. |
status !~ "closed" |
Set membership operators
These operators check whether a field value matches any value in a provided list.
| Operator | Description | Example |
|---|---|---|
in |
Field value exactly matches one of the values in the provided list (case-sensitive). | status in ("Open", "Pending") |
in~ |
Case-insensitive version of in. |
region in~ ("us-east", "US-WEST") |
!in |
Field value does not match any value in the provided list (case-sensitive). | owner !in ("unassigned", "deleted") |
!in~ |
Case-insensitive version of !in. |
region !in~ ("us-east", "US-WEST") |
String and pattern operators
These operators apply to string fields and test for partial matches rather than exact equality.
contains family — checks whether the field value contains the given substring anywhere within it.
| Operator | Description | Example |
|---|---|---|
contains |
Field contains the substring (case-sensitive). | hostname contains "server" |
contains~ |
Field contains the substring (case-insensitive). | hostname contains~ "SERVER" |
!contains |
Field does not contain the substring (case-sensitive). | hostname !contains "test" |
!contains~ |
Field does not contain the substring (case-insensitive). | hostname !contains~ "TEST" |
starts_with family — checks whether the field value begins with the given substring.
| Operator | Description | Example |
|---|---|---|
starts_with |
Field starts with the substring (case-sensitive). | hostname starts_with "web-" |
starts_with~ |
Field starts with the substring (case-insensitive). | hostname starts_with~ "WEB-" |
!starts_with |
Field does not start with the substring (case-sensitive). | hostname !starts_with "temp-" |
!starts_with~ |
Field does not start with the substring (case-insensitive). | hostname !starts_with~ "TEMP-" |
ends_with family — checks whether the field value ends with the given substring.
| Operator | Description | Example |
|---|---|---|
ends_with |
Field ends with the substring (case-sensitive). | hostname ends_with ".local" |
ends_with~ |
Field ends with the substring (case-insensitive). | hostname ends_with~ ".LOCAL" |
!ends_with |
Field does not end with the substring (case-sensitive). | hostname !ends_with ".test" |
!ends_with~ |
Field does not end with the substring (case-insensitive). | hostname !ends_with~ ".TEST" |
like family — wildcard-style pattern matching using % or * wildcards within the pattern.
| Operator | Description | Example |
|---|---|---|
like |
Field matches the wildcard pattern (case-sensitive). | hostname like "web-*" |
like~ |
Field matches the wildcard pattern (case-insensitive). | hostname like~ "WEB-*" |
!like |
Field does not match the wildcard pattern (case-sensitive). | hostname !like "temp-*" |
!like~ |
Field does not match the wildcard pattern (case-insensitive). | hostname !like~ "TEMP-*" |
contains, starts_with, or ends_with for simple substring checks — they are clearer and typically faster. Use like when you need wildcard patterns with matches anywhere in the string. Use matches regex for full regular expression matching.
Advanced operators
For simple substring checks, use contains, starts_with, or ends_with. These options are clearer and typically faster.
| Operator | Description | Example |
|---|---|---|
between |
Field value falls within an inclusive range [min .. max]. |
score between (70 .. 100) |
!between |
Field value falls outside the given range. | age !between (18 .. 65) |
Regex operator — evaluates a full regular expression pattern against a field value.
| Operator | Description | Example |
|---|---|---|
matches regex |
Field value matches the given regular expression pattern. Unlike =~ and !~, which perform case-insensitive equality checks, this operator evaluates a full regex pattern against the value. |
hostname matches regex @"^web-[0-9]{3}$" |
Collection operators
These operators apply to fields that hold multiple values, such as arrays, sets, or tag lists.
has family — checks whether the collection contains one specific, complete term. The term must match a full element — this is not a substring match.
| Operator | Description | Example |
|---|---|---|
has |
Collection contains the exact term (case-sensitive). | tags has "critical" |
has~ |
Collection contains the exact term (case-insensitive). | labels has~ "CRITICAL" |
!has |
Collection does not contain the term (case-sensitive). | tags !has "deprecated" |
!has~ |
Collection does not contain the term (case-insensitive). | labels !has~ "DEPRECATED" |
has_any family — checks whether the collection contains at least one of several given terms.
| Operator | Description | Example |
|---|---|---|
has_any |
Collection contains at least one of the listed terms (case-sensitive). | tags has_any ("urgent", "security") |
has_any~ |
Case-insensitive version of has_any. |
tags has_any~ ("URGENT", "SECURITY") |
!has_any |
Collection contains none of the listed terms (case-sensitive). | tags !has_any ("spam", "ignore") |
!has_any~ |
Case-insensitive version of !has_any. |
tags !has_any~ ("SPAM", "IGNORE") |
has_all family — checks whether the collection contains every one of several given terms.
| Operator | Description | Example |
|---|---|---|
has_all |
Collection contains all of the listed terms (case-sensitive). | permissions has_all ("read", "write") |
has_all~ |
Case-insensitive version of has_all. |
permissions has_all~ ("READ", "WRITE") |
!has_all |
Collection is missing at least one of the listed terms (case-sensitive). | permissions !has_all ("read", "admin") |
!has_all~ |
Case-insensitive version of !has_all. |
permissions !has_all~ ("READ", "ADMIN") |
has and contains have different use cases for substring matching within a single string value. has performs whole-term matching against elements of a multi-value collection. For a field with value ["backup", "server"], has "server" matches, but has "serv" does not.
AQL pipeline predicates
AQL queries are built as a pipeline of stages. Each stage begins with a predicate (verb) preceded by the pipe character (|) and transforms the result of the previous stage.
| Predicate | Description | Example |
|---|---|---|
where |
Filters rows using a predicate built from AQL operators. This is the primary filtering stage. | | where severity == "High" |
project |
Selects and optionally renames specific columns to include in the output, discarding all others. Use this to shape the result set to only the columns you need. | | project ticket_id, title, owner |
summarize |
Aggregates rows into summary statistics (count, sum, avg, min, max), optionally grouped by one or more columns. Similar to SQL GROUP BY. |
| summarize count() by owner |
sort |
Orders the result rows by one or more columns, ascending or descending. | | sort by age_hours desc |
top |
Returns the top N rows according to specified sort criteria. Equivalent to sort followed by a row limit. |
| top 20 by age_hours |
render |
Renders the result as a chart or visualization (for example, a pie chart or line chart) instead of a raw table. | | render barchart |