> ## Documentation Index
> Fetch the complete documentation index at: https://axiom-mano-sample-app.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# String operators

> Learn how to use and combine different query operators for searching string data types.

## String operators

Axiom processing language provides you with different query operators for searching string data types.

Below are the list of string operators we support on Axiom processing language.

**Note:**

The following abbreviations are used in the table below:

* RHS = right hand side of the expression.
* LHS = left hand side of the expression.

Operators with an \_cs suffix are case sensitive

When two operators do the same task, use the case-sensitive one for better performance.

For example:

* instead of `=~`, use `==`
* instead of `in~`, use `in`
* instead of `contains`, use `contains_cs`

The table below shows the list of string operators supported by Axiom processing language:

| **Operator**        | **Description**                         | **Case-Sensitive** | **Example**                             |
| ------------------- | --------------------------------------- | ------------------ | --------------------------------------- |
| **==**              | Equals                                  | Yes                | `"aBc" == "aBc"`                        |
| **!=**              | Not equals                              | Yes                | `"abc" != "ABC"`                        |
| **=\~**             | Equals                                  | No                 | `"abc" =~ "ABC"`                        |
| **!\~**             | Not equals                              | No                 | `"aBc" !~ "xyz"`                        |
| **contains**        | RHS occurs as a subsequence of LHS      | No                 | `parentSpanId` contains `Span`          |
| **!contains**       | RHS doesn’t occur in LHS                | No                 | `parentSpanId` !contains `abc`          |
| **contains\_cs**    | RHS occurs as a subsequence of LHS      | Yes                | `parentSpanId` contains\_cs "Id"        |
| **!contains\_cs**   | RHS doesn’t occur in LHS                | Yes                | `parentSpanId` !contains\_cs "Id"       |
| **startswith**      | RHS is an initial subsequence of LHS    | No                 | `parentSpanId` startswith `parent`      |
| **!startswith**     | RHS isn’t an initial subsequence of LHS | No                 | `parentSpanId` !startswith "Id"         |
| **startswith\_cs**  | RHS is an initial subsequence of LHS    | Yes                | `parentSpanId` startswith\_cs "parent"  |
| **!startswith\_cs** | RHS isn’t an initial subsequence of LHS | Yes                | `parentSpanId` !startswith\_cs "parent" |
| **endswith**        | RHS is a closing subsequence of LHS     | No                 | `parentSpanId` endswith "Id"            |
| **!endswith**       | RHS isn’t a closing subsequence of LHS  | No                 | `parentSpanId` !endswith `Span`         |
| **endswith\_cs**    | RHS is a closing subsequence of LHS     | Yes                | `parentSpanId` endswith\_cs `Id`        |
| **!endswith\_cs**   | RHS isn’t a closing subsequence of LHS  | Yes                | `parentSpanId` !endswith\_cs `Span`     |
| **in**              | Equals to one of the elements           | Yes                | `abc` in ("123", "345", "abc")          |
| **!in**             | Not equals to any of the elements       | Yes                | "bca" !in ("123", "345", "abc")         |
| **in\~**            | Equals to one of the elements           | No                 | "abc" in\~ ("123", "345", "ABC")        |
| **!in\~**           | Not equals to any of the elements       | No                 | "bca" !in\~ ("123", "345", "ABC")       |
| **!matches regex**  | LHS doesn’t contain a match for RHS     | Yes                | `parentSpanId` !matches regex `g.*r`    |
| **matches regex**   | LHS contains a match for RHS            | Yes                | `parentSpanId` matches regex `g.*r`     |
| **has**             | RHS is a whole term in LHS              | No                 | `Content Type` has `text`               |
| **has\_cs**         | RHS is a whole term in LHS              | Yes                | `Content Type` has\_cs `Text`           |

## Use string operators efficiently

String operators are fundamental in comparing, searching, or matching strings. Understanding the performance implications of different operators can significantly optimize your queries. Below are performance tips and query examples.

## Equality and Inequality Operators

* Operators: `==`, `!=`, `=~`, `!~`, `in`, `!in`, `in~`, `!in~`

Query Examples:

```kusto
"get" == "get"
"get" != "GET"
"get" =~ "GET"
"get" !~ "put"
"get" in ("get", "put", "delete")
```

* Use `==` or `!=` for exact match comparisons when case sensitivity is important, as they are faster.
* Use `=~` or `!~` for case-insensitive comparisons, or when the exact case is unknown.
* Use `in` or `!in` for checking membership within a set of values, which can be efficient for a small set of values.

## Subsequence Matching Operators

* Operators: `contains`, `!contains`, `contains_cs`, `!contains_cs`, `startswith`, `!startswith`, `startswith_cs`, `!startswith_cs`, `endswith`, `!endswith`, `endswith_cs`, `!endswith_cs`.

Query Examples:

```kusto
"parentSpanId" contains "Span" // True
"parentSpanId" !contains "xyz" // True
"parentSpanId" startswith "parent" // True
"parentSpanId" endswith "Id" // True
"parentSpanId" contains_cs "Span" // True if parentSpanId is "parentSpanId", False if parentSpanId is "parentspanid" or "PARENTSPANID"
"parentSpanId" startswith_cs "parent" // True if parentSpanId is "parentSpanId", False if parentSpanId is "ParentSpanId" or "PARENTSPANID"
"parentSpanId" endswith_cs "Id" // True if parentSpanId is "parentSpanId", False if parentSpanId is "parentspanid" or "PARENTSPANID"
```

* Use case-sensitive operators (`contains_cs`, `startswith_cs`, `endswith_cs`) when the case is known, as they are faster.

## Regular Expression Matching Operators

* Operators: `matches regex`, `!matches regex`

```kusto
"parentSpanId" matches regex "p.*Id" // True
"parentSpanId" !matches regex "x.*z" // True
```

* Avoid complex regular expressions or use string operators for simple substring, prefix, or suffix matching.

## Term Matching Operators

* Operators: `has`, `has_cs`

Query Examples:

```kusto
"content type" has "type" // True
"content type" has_cs "Type" // False
```

* Use `has` or `has_cs` for term matching which can be more efficient than regular expression matching for simple term searches.
* Use `has_cs` when the case is known, as it is faster due to case-sensitive matching.

## Best Practices

* Always use case-sensitive operators when the case is known, as they are faster.
* Avoid complex regular expressions for simple matching tasks; use simpler string operators instead.
* When matching against a set of values, ensure the set is as small as possible to improve performance.
* For substring matching, prefer prefix or suffix matching over general substring matching for better performance.

## has operator

The `has` operator in APL filters rows based on whether a given term or phrase appears within a string field.

## Importance of the `has` operator:

* **Precision Filtering:** Unlike the `contains` operator, which matches any substring, the `has` operator looks for exact terms, ensuring more precise results.

* **Simplicity:** Provides an easy and readable way to find exact terms in a string without resorting to regex or other more complex methods.

The following table compares the `has` operators using the abbreviations provided:

* RHS = right-hand side of the expression
* LHS = left-hand side of the expression

| Operator      | Description                                                   | Case-Sensitive | Example                                |
| ------------- | ------------------------------------------------------------- | -------------- | -------------------------------------- |
| has           | Right-hand-side (RHS) is a whole term in left-hand-side (LHS) | No             | "North America" has "america"          |
| has\_cs       | RHS is a whole term in LHS                                    | Yes            | "North America" has\_cs "America"      |
| hassuffix     | LHS string ends with the RHS string                           | No             | "documentation.docx" hassuffix ".docx" |
| hasprefix     | LHS string starts with the RHS string                         | No             | "Admin\_User" hasprefix "Admin"        |
| hassuffix\_cs | LHS string ends with the RHS string                           | Yes            | "Document.HTML" hassuffix\_cs ".HTML"  |
| hasprefix\_cs | LHS string starts with the RHS string                         | Yes            | "DOCS\_file" hasprefix\_cs "DOCS"      |

## Syntax

```kusto
['Dataset'] 
| where Field has (Expression)
```

## Parameters

| Name       | Type              | Required | Description                                                                                                    |
| ---------- | ----------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| Field      | string            | ✓        | The field filters the events.                                                                                  |
| Expression | scalar or tabular | ✓        | An expression for which to search. The first field is used if the value of the expression has multiple fields. |

## Returns

The `has` operator returns rows from the dataset where the specified term is found in the given field. If the term is present, the row is included in the result set; otherwise, it is filtered out.

## Example

```kusto
['sample-http-logs']
| summarize event_count = count() by content_type
| where content_type has "text"
| where event_count > 10
| project event_count, content_type
```

[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B%27sample-http-logs%27%5D%5Cn%7C%20summarize%20event_count%20%3D%20count%28%29%20by%20content_type%5Cn%7C%20where%20content_type%20has%20%5C%22text%5C%22%5Cn%7C%20where%20event_count%20%3E%2010%5Cn%7C%20project%20event_count%2C%20content_type%22%7D\&queryOptions=%7B%22quickRange%22%3A%2230d%22%7D)

## Output

| event\_count | content\_type            |
| ------------ | ------------------------ |
| 132,765      | text/html                |
| 132,621      | text/plain-charset=utf-8 |
| 89,085       | text/csv                 |
| 88,436       | text/css                 |
