Filtering and selecting are fundamental operations when working with data streams. This guide shows you how to filter events based on conditions and select specific fields from your data.
Understanding operators vs functions
Section titled “Understanding operators vs functions”Before we dive in, it’s important to understand a key distinction in TQL:
- Operators like
where,select, anddropwork on entire event streams - Functions like
starts_with()or mathematical comparisons work on individual values within events
You’ll see both in action throughout this guide.
Filter events with conditions
Section titled “Filter events with conditions”Use the where operator to keep only events that
match specific conditions.
Basic filtering
Section titled “Basic filtering”Filter events based on a simple condition. This example keeps only successful HTTP requests (status code 200):
from {status: 200, path: "/api/users"}, {status: 404, path: "/api/missing"}, {status: 200, path: "/home"}where status == 200{status: 200, path: "/api/users"}{status: 200, path: "/home"}The event with status: 404 is filtered out because it doesn’t match our condition.
Combining conditions
Section titled “Combining conditions”Use logical operators (and, or, not) to combine multiple conditions:
from {status: 200, path: "/api/users", size: 1024}, {status: 404, path: "/api/missing", size: 512}, {status: 200, path: "/home", size: 2048}where status == 200 and size > 1000{status: 200, path: "/api/users", size: 1024}{status: 200, path: "/home", size: 2048}You can also use or and not with functions like starts_with():
from {status: 200, path: "/api/users"}, {status: 404, path: "/api/missing"}, {status: 500, path: "/api/error"}where status == 200 or not path.starts_with("/api/m"){status: 200, path: "/api/users"}{status: 500, path: "/api/error"}Using functions in filters
Section titled “Using functions in filters”Functions work on values to create more sophisticated filters. For example,
ends_with() checks string suffixes:
from {user: "alice", email: "alice@example.com"}, {user: "bob", email: "bob@gmail.com"}, {user: "charlie", email: "charlie@example.com"}where email.ends_with("example.com"){user: "alice", email: "alice@example.com"}{user: "charlie", email: "charlie@example.com"}Filtering with patterns
Section titled “Filtering with patterns”Match patterns using regular expressions with
match_regex():
from {log: "Error: Connection timeout"}, {log: "Info: Request processed"}, {log: "Error: Invalid input"}where log.match_regex("Error:"){log: "Error: Connection timeout"}{log: "Error: Invalid input"}Select specific fields
Section titled “Select specific fields”The select operator lets you pick which fields
to keep in your output.
Basic field selection
Section titled “Basic field selection”Select only the fields you need:
from {name: "alice", age: 30, city: "NYC"}, {name: "bob", age: 25, city: "SF"}select name, age{name: "alice", age: 30}{name: "bob", age: 25}Renaming fields
Section titled “Renaming fields”You can rename fields while selecting them. This is useful when standardizing field names from different data sources:
from {first_name: "alice", years: 30}, {first_name: "bob", years: 25}select name=first_name, age=years{name: "alice", age: 30}{name: "bob", age: 25}Here first_name becomes name and years becomes age in the output.
Computing new fields
Section titled “Computing new fields”Create new fields with expressions during selection:
from {price: 100, tax_rate: 0.08}, {price: 50, tax_rate: 0.08}select price, tax=price * tax_rate, total=price * (1 + tax_rate){price: 100, tax: 8.0, total: 108.0}{price: 50, tax: 4.0, total: 54.0}Remove unwanted fields
Section titled “Remove unwanted fields”The drop operator removes specified fields,
keeping everything else.
Basic field removal
Section titled “Basic field removal”Remove fields you don’t need:
from {user: "alice", password: "secret", email: "alice@example.com"}, {user: "bob", password: "hidden", email: "bob@example.com"}drop password{user: "alice", email: "alice@example.com"}{user: "bob", email: "bob@example.com"}Dropping multiple fields
Section titled “Dropping multiple fields”Remove several fields at once:
from {id: 1, internal_id: "xyz", debug: true, name: "alice"}, {id: 2, internal_id: "abc", debug: false, name: "bob"}drop internal_id, debug{id: 1, name: "alice"}{id: 2, name: "bob"}Add computed fields
Section titled “Add computed fields”Use the set operator to override existing fields
and add new fields without removing existing ones.
Adding simple fields
Section titled “Adding simple fields”Add a constant field to all events:
from {user: "alice"}, {user: "bob"}set source = "api"{user: "alice", source: "api"}{user: "bob", source: "api"}Computing field values
Section titled “Computing field values”Add fields based on calculations:
from {bytes_sent: 1024, bytes_received: 2048}, {bytes_sent: 512, bytes_received: 1024}set total_bytes = bytes_sent + bytes_received{bytes_sent: 1024, bytes_received: 2048, total_bytes: 3072}{bytes_sent: 512, bytes_received: 1024, total_bytes: 1536}Using the else keyword
Section titled “Using the else keyword”Use the else word to provide default values for null fields:
from {name: "alice", score: 85}, {name: "bob"}, {name: "charlie", score: 95}score = score? else 0{name: "alice", score: 85}{name: "bob", score: 0}{name: "charlie", score: 95}Combining operations
Section titled “Combining operations”Real-world pipelines often combine multiple operations:
from {method: "GET", path: "/api/users", status: 200, duration_ms: 45}, {method: "POST", path: "/api/users", status: 201, duration_ms: 120}, {method: "GET", path: "/api/users/123", status: 404, duration_ms: 15}where status >= 200 and status < 300select method, path, duration = duration_ms.milliseconds(){method: "GET", path: "/api/users", duration: 45ms}{method: "POST", path: "/api/users", duration: 120ms}Best practices
Section titled “Best practices”-
Filter early: Apply
whereconditions as early as possible to reduce the amount of data flowing through your pipeline. -
Select only what you need: Use
selectto keep only necessary fields, especially when dealing with large events. -
Choose the right operator:
-
Understand null handling: The
whereoperator skips events where the condition evaluates to null or false. Use the question mark operator (?) to suppress warnings when accessing fields that may not exist.
Related guides
Section titled “Related guides”- Shape data - Overview of all shaping operations
- Transform basic values - Learn about value transformations
- Slice and sample data - Control the flow of events