Text search operators

FuseQL text search operators match against the raw log message body or structured field values using patterns, substrings, regular expressions, or token lookups. They must appear before the first pipe (|) in a query. Choose the right operator based on what is indexed: use term for token lookups (fast, index-backed), "phrase" (grep) for literal substring scans, =~ for regex on label and facet values, * / ~ / ~* for substring or prefix or suffix matches, and @facet or key exists to test field presence.

**

Substring filter operator. Selects log lines where a label or facet value contains the specified string anywhere within it. The match is case-sensitive and does not require the string to appear at the start or end.

Syntax

label**"value"
@facet**"value"
none

Parameters

Parameter Required Description

label or @facet

Yes

The label key or (with @ prefix) facet name to filter on.

"value"

Yes

The substring that must appear anywhere in the field value.

Example

Return nginx logs for deployments whose name contains the string ingress-ingress.

source="nginx" and kube_deployment**"ingress-ingress" | count by kube_deployment
Expected output
_count kube_deployment

316505

kfuse-ingress-ingress-nginx-controller

Use * when you know a substring but not the full value. For prefix matching use ~; for suffix matching use ~*; for exact matching use =. The match is case-sensitive.

~*

Suffix match filter operator. Selects log lines where a label or facet value ends with the specified string. This is a faster alternative to a regex anchor (=~"suffix$") for simple suffix checks.

Syntax

label~*"suffix"
@facet~*"suffix"
none

Parameters

Parameter Required Description

label or @facet

Yes

The label or facet name to match against.

"suffix"

Yes

The string that the field value must end with.

Example

Return logs from services whose name ends with service.

source="nginx" @resource_service_name~*"service"
Effect

Returns log lines from the nginx source where resource_service_name ends with service, such as api-service or auth-service.

The ~ operator is case-sensitive. For case-insensitive suffix matching, use the regex operator with the (?i) flag: label=~"(?i)suffix$". Prefer ~ over a regex suffix pattern when the match is a plain literal string.

grep (double-quote search)

Literal substring search operator. Searches for an exact character sequence in the raw log body. Unlike term search (single quotes), which queries an inverted index of whole words, grep scans the reconstructed log body character-by-character — so it can match partial words, camelCase substrings, and multi-word phrases in a specific order.

How it works

Kloudfuse stores each log line as a fingerprint (the structural template) plus a list of extracted variable values. At query time, grep reconstructs the full log message from these parts and scans the result as a character sequence using the kf_log_grep_match function inside the query engine. No inverted index is used for plain substring greps.

For regex greps (patterns containing * or ? wildcards, or =~ on labels/facets), the engine applies an optimization: a literal prefix is extracted from the pattern and used to pre-filter candidate lines via the Lucene text index, and then a per-row RE2 regex check validates the exact match. This makes regex greps faster than a pure scan, but they are still slower than term searches for whole-word lookups.

Key properties:

  • Matches are case-sensitive"Error" does not match error.

  • Partial-word matches succeed — "error" matches errored, errors, and error_count.

  • Multi-word phrases must appear in the exact character sequence"connection refused" only matches lines where those two words appear adjacent and in that order.

  • Wildcards (any characters) and ? (any single character) are supported — "err" matches error, errored, errors.

Grep vs. term search

Property Grep ("…") Term search ('…')

Match type

Literal character substring in the reconstructed log body

Whole words from the Lucene inverted index on log_line

Token boundaries

No — "error" matches errored, errors, error_count as character sequences

Yes — 'error' does not match errored; does match error_count (underscore is a delimiter)

Case sensitivity

Case-sensitive

Case-insensitive (Lucene lowercases at ingest)

Wildcards

Yes — "err*" and "err?r" are supported

No

Speed

Slower — per-row body reconstruction and scan

Faster — index lookup

Multi-word

Exact ordered phrase

Both words present anywhere in the line (AND, any order)

Use grep when you need an exact phrase match, need to match a partial word or camelCase substring, or need wildcard patterns. Use term search for whole-word lookups where speed matters.

Syntax

"expression"
"wild*card"
none

Parameters

Parameter Required Description

"expression"

Yes

A double-quoted literal string or wildcard pattern to match as a character sequence in the raw log body. The match is case-sensitive. Use * for zero or more characters and ? for any single character.

Example

Return logs whose body contains the exact phrase Connection refused:

"Connection refused"
Effect

Returns log lines where the character sequence Connection refused appears in the raw log body. connection refused (different case) and Connection: refused (colon inserted) do not match.

Return nginx access logs for any path under /api/:

source="nginx" "GET /api/*"
Effect

Returns nginx log lines whose body matches the pattern — for example, GET /api/orders and GET /api/users both match.

key exists

Facet presence filter operator. Selects log lines where a specific facet key is present in the log entry, regardless of the value it holds. In regular search, use the key exists keyword syntax; in advanced search, reference the facet name with the @ prefix alone.

Syntax

key exists="facetName"
none

Parameters

Parameter Required Description

facetName

Yes

The name of the facet whose presence to check. In regular search, quoted as a string value; in advanced search, prefixed with @.

Example

Return log lines that have a user_agent_original facet (any value), to filter for requests that include a user-agent header.

source="nginx" @user_agent_original
Effect

Returns log lines from the nginx source where the user_agent_original facet is present, regardless of its value.

Use key exists to identify log lines that were enriched with a specific facet, or to find entries from agents or integrations that emit a particular field. Combine with value operators to further narrow results: @user_agent_original and @user_agent_original!~".bot.".

not-grep (negated double-quote search)

Literal substring exclusion operator. Excludes log lines whose raw log body contains the specified exact character sequence. This is the logical complement of the grep ("expression") operator — everything that grep would match is excluded. Wildcards are supported.

Syntax

!"expression"
!"wild*card"
none

Parameters

Parameter Required Description

"expression"

Yes

A double-quoted literal string or wildcard pattern; any log line whose raw body contains a match is excluded. The match is case-sensitive. Use * for zero or more characters and ? for any single character.

Example

Exclude health-check noise from nginx logs:

source="nginx" !"GET /health*"
Effect

Returns all nginx log lines except those whose body matches the pattern GET /health* — for example, GET /health and GET /healthz are both excluded.

!"expression" (not-grep) scans for substrings in the raw log body and is case-sensitive. It is distinct from !'term' (not-terms-exist), which queries the Lucene inverted index for whole-word tokens and is case-insensitive. Use not-grep when you need to exclude a partial word, an exact phrase, or a case-specific sequence. Use !'term' when you want to exclude log lines containing a specific whole word.

!~

Regex exclusion filter operator. Selects log lines where a label or facet value does not match the specified regular expression pattern. This is the logical complement of =~. As with =~, patterns are automatically anchored — label!~"foo" excludes lines where the value is exactly "foo", not lines where it merely contains "foo".

Syntax

label!~"pattern"
@facetName!~"pattern"
none

Parameters

Parameter Required Description

label or @facetName

Yes

The label or facet name to match against.

"pattern"

Yes

A RE2-compliant regular expression string; lines where the value matches this pattern are excluded.

Example

Return nginx logs from namespaces that do not contain kfuse.

source="nginx" kube_namespace!~"kfuse.*"
Effect

Returns log lines from the nginx source where kube_namespace does not match kfuse.*.

Patterns are automatically anchored, so explicit ^ and $ are not needed. To exclude lines where a value merely contains a substring, use . around your pattern: label!~".*foo.". Combine !~ with =~ to build allow-and-deny filter lists.

not-term (negated single-quote search)

Token exclusion operator. Excludes log lines whose raw log body contains all of the specified whole words. This is the logical complement of the term search ('term') operator — it queries the Lucene inverted index and excludes any line where every specified token is present as a whole word.

When you use multiple words such as !'Finished API', a log line is excluded only if both finished and api appear somewhere in the line (each word is matched independently, not as a phrase). A line containing only finished or only api is not excluded. This mirrors the AND logic of term search.

Syntax

!'term'
NOT 'term'
!'term1 term2'
none

Parameters

Parameter Required Description

'term'

Yes

A single-quoted word or space-separated words. Each word is matched independently as a whole token. A log line is excluded only if it contains all listed tokens as whole words. A line that is missing any one of the tokens is included in results.

Example

Suppress high-volume polling traffic that would otherwise dominate results:

!'healthcheck'
Effect

Excludes log lines where healthcheck appears as a whole token. Lines containing kube-healthcheck are also excluded — the hyphen is a token boundary, making healthcheck a distinct token. Lines containing healthcheck_endpoint are not excluded — the underscore keeps the whole string as one token (healthcheck_endpoint), so healthcheck alone does not match it. Lines containing healthchecking are not excluded either (no boundary after healthcheck).

!'term' (not-terms-exist) is token-based and case-insensitive. It excludes a line only when the term appears as a complete token — delimited by whitespace or punctuation such as hyphens, colons, and slashes. Underscores and dots do not split tokens: !'error' excludes lines where error is a standalone token (e.g. error, Error, ERROR, or error-rate where the hyphen creates a boundary) but does not exclude error_count (underscore keeps it as one token) or errored (no boundary). For substring exclusion regardless of token boundaries, use !"expression" (not-grep).

Stop words

Stop words are stripped from negated term search queries before the index lookup, exactly as they are in positive term search. If all words in the expression are stop words, the query becomes empty and excludes nothing (all lines are returned).

The following words are stripped:

a, an, and, are, as, at, be, but, by, for, if, in, into, is, it, no, not, of, on, or, such, than, that, the, their, then, there, these, they, this, those, to, was, will, with

For example, !'is not' strips both words, producing an empty expression — the operator matches nothing and all log lines are returned. For stop-word phrase exclusion use not-grep: !"is not".

=~

Regex match filter operator. Selects log lines where a label or facet value matches the specified regular expression pattern. The match is full-value by default — the pattern is automatically anchored, so label=~"foo" matches only "foo", not "foobar". Use . around your pattern if you want a substring match: label=~".*foo.".

Syntax

label=~"pattern"
@facetName=~"pattern"
none

Parameters

Parameter Required Description

label or @facetName

Yes

The label or facet name to match against.

"pattern"

Yes

A RE2-compliant regular expression string.

Example

Return nginx logs from any namespace whose name starts with kfuse.

source="nginx" kube_namespace=~"kfuse.*"
Effect

Returns log lines from the nginx source where the kube_namespace label matches the pattern kfuse.* (any value beginning with kfuse).

The regex engine does not support look-ahead or look-behind assertions. For case-insensitive matching, use the inline flag (?i): label=~"(?i)nginx". Because patterns are automatically anchored, adding explicit ^ and $ anchors is unnecessary and results in double-anchoring.

*~

Prefix match filter operator. Selects log lines where a label or facet value begins with the specified string. This is a faster alternative to a regex anchor (=~"^prefix") for simple prefix checks.

Syntax

label*~"prefix"
@facet*~"prefix"
none

Parameters

Parameter Required Description

label or @facet

Yes

The label or facet name to match against.

"prefix"

Yes

The string that the field value must start with.

Example

Return logs from containers whose name starts with kfuse.

source="nginx" kube_container_name*~"kfuse"
Effect

Returns log lines from the nginx source where kube_container_name begins with kfuse, such as kfuse-api-server or kfuse-ingress.

The ~ operator is case-sensitive. For case-insensitive prefix matching, use the regex operator with the (?i) flag: label=~"(?i)^prefix". Prefer ~ over a regex prefix pattern when the match is purely literal — it is more readable and may execute faster.

term (single-quote search)

Token search operator. Selects log lines whose raw log body contains the specified token or tokens. Unlike grep (double quotes), which scans the reconstructed character sequence, term search queries the Lucene inverted index built from the raw log_line column at ingest time — making it faster for whole-token lookups.

When you enter multiple words such as 'Finished API', term search looks up each word independently. It is not a phrase search. Both words must appear somewhere in the log line, but they can be anywhere in the line and in any order. To match an exact sequence of words, use grep ("Finished API") instead.

How it works

At ingest, the raw log line is tokenized by Pinot’s Lucene analyzer: text is split on whitespace and punctuation (spaces, hyphens, colons, slashes, brackets, and similar characters), and each token is lower-cased. Dots (.) and underscores (_) do not split tokens. These tokens are stored in an inverted index that maps each token to the set of log lines containing it.

A term search looks up each token in that index directly — no per-row reconstruction or scanning of raw log bodies occurs.

Single-word search

'error' matches a line containing error, Error, or ERROR (case-insensitive). It also matches error-rate because hyphens are token boundaries that split error into its own token. It does not match error_count (underscore keeps the token whole — error_count is a single token, not two) or errored and errors (no boundary after error).

Multi-word search

'Finished API' (two words) tokenizes to finished and api. Each token is looked up in the Lucene index independently. A log line is returned only if it contains both tokens as separate whole words — but the words can appear anywhere in the line and in any order.

This means:

  • 'Finished API' matches Finished processing the API request

  • 'Finished API' matches API call Finished with status 200 ✅ (any order)

  • 'Finished API' does not match Finished processing the request ❌ (only finished, no api)

  • 'Finished API' does not match API call started ❌ (only api, no finished)

  • 'Finished API' is not the same as "Finished API" (grep) — grep requires the exact sequence Finished API with a space between them

Stop words

Common English words are removed from term search queries before the Lucene index lookup. If your search consists entirely of stop words, the query becomes empty and matches nothing.

The following words are stripped:

a, an, and, are, as, at, be, but, by, for, if, in, into, is, it, no, not, of, on, or, such, than, that, the, their, then, there, these, they, this, those, to, was, will, with

For example, 'is not valid' strips is and not, leaving only valid. The search 'is not' strips both words and matches nothing.

See Stop words for tokenization examples.

Term search vs. grep

Property Term search ('…') Grep ("…")

Match type

Whole words from the Lucene inverted index on log_line

Literal character substring in the reconstructed log body

Token boundaries

Yes — 'error' does not match errored or error_count (underscore keeps the token whole); does match error-rate (hyphen splits)

No — "error" matches errored, errors, error_count as character sequences

Case sensitivity

Case-insensitive

Case-sensitive

Wildcards

No

Yes — * and ? supported

Multi-word behavior

Each word searched independently; both must be present anywhere in the line (AND, any order — not a phrase)

Exact ordered phrase — words must appear adjacent in the specified order

Speed

Faster — index lookup

Slower — per-row body reconstruction and scan

Use term search when you want whole-word matching and speed. Use grep when you need to match a specific sequence of words, a partial word, a camelCase substring, or a wildcard pattern.

Syntax

'term'
'term1 term2'
none

Parameters

Parameter Required Description

term

Yes

A single-quoted word or space-separated words. Each word is matched independently as a whole lower-cased token from the Lucene index. When multiple words are given, every word must appear somewhere in the log line (logical AND) — this is not a phrase search.

Examples

Return log lines that contain the whole word timeout (not timeouts or timed_out):

'timeout'

Return log lines that contain both the word connection and the word refused, anywhere in the line and in any order:

'connection refused'
Effect

Matches the connection was refused by the server ✅ and refused — connection dropped ✅. Does not match connection lost ❌ (no refused token) or service refused entry ❌ (no connection token). Also matches connection-refused because the hyphen is a token boundary making connection and refused separate tokens.

Return log lines that contain both finished and api, in any order, anywhere in the line:

'Finished API'
Effect

Matches Finished processing the API request ✅ and API call Finished with 200 ✅. Does not match Finished processing the request ❌ or API call started ❌. To require the exact phrase, use "Finished API" (grep) instead.

Limitations

  • Not a phrase search. 'word1 word2' does not guarantee the words appear adjacent or in order. Use grep for phrase matching.

  • No partial-token matching. 'schedule' does not match the token com.example.scheduler.Job. The full dot-separated string is a single token.

  • Stop words are silently dropped. Searching 'is not valid' strips is and not, leaving only valid. If your intent depends on stop words, use grep.

  • No wildcard support. Use grep ("err*") for wildcard patterns.

  • Not supported on view queries. Term search cannot be used with _view=… queries.

  • Case-insensitive only. You cannot perform a case-sensitive term search; use grep if case matters.

Best practices

  • Use term search for keyword lookups — individual words such as error, timeout, or failed where position does not matter.

  • When searching for a phrase (words that must appear together in order), use grep: "Finished API".

  • When searching for multiple independent keywords that must all appear, term search is the right tool: 'Finished API' finds lines containing both words anywhere.

  • Avoid using only stop words such as 'is not' — both words are removed, producing an empty query that matches nothing.

  • Prefer term search over grep for performance when whole-word matching is sufficient; term search uses the index directly while grep scans each log body.

  • If term search returns too many results (because the tokens appear frequently), add more words to narrow the match: 'connection refused timeout' requires all three tokens.