Common Query Patterns
CrowdStrike Query Language (CQL) has many different functions, syntax, and methods for querying and processing data. This can mean that there are multiple ways to achieve the same result. This guide provides different solutions for achieving the results based on the activity or action, rather than requiring you to know the function.
For more detailed examples of queries, including the ability to search for specific functions and syntax, see Examples Library.
The following sections provide practical examples organized by common tasks and categories:
Common Misconceptions: Understand common mistakes and misconceptions when writing CQL queries
Converting Data: Convert data types, parse JSON/XML, and handle encoded data
Modifying Data: Modify and manipulate data including numerical calculations and string operations
Array Operations: Work with arrays including concatenation, flattening, and element access
Deduplicating Data: Remove duplicate data from results
Limiting Returned Events: Control the number of events returned
Sorting Data: Sort and order query results
Formatting Values: Format values for display including numbers and timestamps
LogScale and Time: Work with time operations including parsing, formatting, and time ranges
Other Tricks and Recipes: Additional tips and techniques
Data Conversion
Time Operations
Formatting and Display
Data Manipulation
Filtering and Sorting
Common Mistakes and Misconceptions
Evaluating Array Elements
One way to process arrays into the format or structure required is to make
use of evaulation and iterate over each element, extracting or
reformatting each element of the array in the process. Two functions
exist, array:eval() which operates on simple arrays
(array[]) and objectArray:eval() which
operates on nested arrays, where each element of the array compound
Converting Compound Arrays
With an input source like this:
| in[0].key = x |
| in[0].value = y |
| in[1].key = a |
| in[1].value = b |
You can convert this into key/value pairs in two ways. If you know how elements:
setField(target=in[0].key, value=in[0].value)
| setField(target=in[1].key, value=in[1].value)Creates an event like this:
| a | x |
|---|---|
| b | y |
If you do not know the length of the array, use
objectArray:eval() to construct new event values and
then re-parse the generated output using kvParse():
objectArray:eval(array="in[]", asArray="out[]", function={out := format(format="%s=%s", field=[in.key, in.value])})
| concatArray("out", as=out, separator=",")
| kvParse(out)This will handle a source array of any length, although the entire process is expensive to generate and then reparse.
Manipulating Complex Arrays
If your arrays are more complex, or if they are object arrays with
multiple levels of detail embedded in one or more array fields, add the
split() function to your query. The function splits
one event into multiple events, one for each element of the source array.
Each new event duplicates the remaining fields from the source event. As a
result, you can manipulate array data directly, instead of extracting each
field value with the array namespace format.