> For the complete documentation index, see [llms.txt](https://docs.mediarithmics.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.mediarithmics.io/setup-and-monitor/operate-and-monitor/query-your-datamart/otql.md).

# OTQL

The Object Tree Query Language: what it is for, and how a query is put together.

## Your goal

Write queries against the whole object graph - to count, to explore, and to define segments.

## Expected outcome

Queries that return the population you meant, on a graph of millions or billions of objects.

## What OTQL is

The **Object Tree Query Language** is designed to search and calculate aggregates on a large collection of **object trees**. The object tree is defined in your [schema](/setup-and-monitor/collect-and-manage-your-data/design-your-data-model-and-schema/schema-definition.md) by the `@TreeIndexRoot` and `@TreeIndex` directives.

{% hint style="success" %}
OTQL queries help you build segments, explore data, monitor data integration, check volumetry, and build data exports.
{% endhint %}

An OTQL query looks like SQL:

```sql
SELECT { id name } FROM Product WHERE price > 50.0
```

It has three parts:

```sql
SELECT [Operation] FROM [Object Type] WHERE [Object Tree Expression]
```

| Part                               | What it does                                                                                       |
| ---------------------------------- | -------------------------------------------------------------------------------------------------- |
| `SELECT` **operation**             | What to do: extract field values, or calculate aggregates.                                         |
| `FROM` **starting object type**    | The object type the evaluation starts from.                                                        |
| `WHERE` **object tree expression** | A logical expression mixing boolean operators and field operators, connecting objects in the tree. |

There are two kinds of operation:

* **Selection operations** are similar to a GraphQL operation, and return a list of objects containing the required fields.
* **Aggregation operations** return aggregated values - counts, statistics, histograms - calculated on the selected objects.

{% hint style="info" %}
**The fields available in a query are entirely determined by how you built your schema.** A field with no `@TreeIndex` directive can be selected but not filtered on.
{% endhint %}

## What a query looks like in practice

```sql
-- New users in the past 7 days
SELECT @count{} FROM UserPoint WHERE creation_date >= "now-7d/d"

-- Transactions on a specific channel, 7 days ago
SELECT @count{} FROM UserEvent
WHERE name = "$transaction_confirmed"
        AND date = "now-7d/d"
        AND channel_id = 2419

-- All event names collected in the platform
SELECT {name @map} FROM UserEvent

-- Users with at least 3 laptop events in the past 15 days
SELECT @count{} FROM UserPoint
WHERE activities { events @ScoreSum(min:3) {
        category = "Laptop" AND date >= "now-15d/d"
        }}

-- Transactions per channel and per day
SELECT { channel_id @map { date @date_histogram } } FROM UserEvent
WHERE name = "$transaction_confirmed"

-- Users with an account but no email
SELECT @count{} FROM UserPoint WHERE accounts{} AND NOT emails{}
```

The full language - operators, scoring, aggregations, joins, limits - is in [OTQL documentation](/setup-and-monitor/operate-and-monitor/query-your-datamart/otql/otql-documentation.md), and more worked queries are in [OTQL examples](/setup-and-monitor/operate-and-monitor/query-your-datamart/otql/otql-examples.md).

## Where to start from

Given this object tree:

```
UserPoint
├── UserActivity
│   └── UserEvent
├── UserEmail
└── UserAccount
```

you can start a query from any of those types, and the equivalent forms are worth knowing:

```sql
SELECT {name} FROM UserEvent
-- is equivalent to
SELECT { activities { events { name }}} FROM UserPoint
```

{% hint style="warning" %}
`FROM` targets an **object type**, not the link field. In the tree above the link field is `activities`, but you write `FROM UserActivity`, never `FROM activities`.
{% endhint %}

The choice of starting type changes what a count counts: `FROM UserPoint` counts people, `FROM UserEvent` counts events.

## Where you write OTQL

| Context                        | What it does                                                                                                                                                    |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Query Tool**, in Data Studio | Interactive exploration. See [Query Tool](/setup-and-monitor/operate-and-monitor/query-your-datamart/query-tool.md).                                            |
| **Segment definitions**        | A `USER_QUERY` segment is an OTQL query.                                                                                                                        |
| **The Query API**              | Saved queries, executed programmatically. See [Query API](/setup-and-monitor/operate-and-monitor/query-your-datamart/query-api.md).                             |
| **Segment metrics**            | Each metric is an OTQL query returning a number. See [Segment metrics](/setup-and-monitor/plan-and-integrate/set-up-the-environment/set-up-segment-metrics.md). |
| **Query exports**              | An export is built on a saved query. See [Export](/setup-and-monitor/collect-and-manage-your-data/export-your-data/export.md).                                  |
| **Dashboards**                 | Cards are backed by queries. See [Create a custom dashboard](/setup-and-monitor/operate-and-monitor/create-a-custom-dashboard.md).                              |

{% hint style="danger" %}
A query behaves differently in some of those contexts. `LIMIT` is **ignored during segment calculation**: a `USER_QUERY` segment built with a `LIMIT` returns every UserPoint matching the `WHERE` clause. See [OTQL documentation](/setup-and-monitor/operate-and-monitor/query-your-datamart/otql/otql-documentation.md#limit).
{% endhint %}

## In this section

<table data-view="cards" data-search="false"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>OTQL documentation</strong></td><td>The language reference: operators, scoring, aggregations.</td><td><a href="/setup-and-monitor/operate-and-monitor/query-your-datamart/otql/otql-documentation.md">OTQL documentation</a></td></tr><tr><td><strong>OTQL examples</strong></td><td>Queries to start from.</td><td><a href="/setup-and-monitor/operate-and-monitor/query-your-datamart/otql/otql-examples.md">OTQL examples</a></td></tr></tbody></table>

## Related pages

<table data-view="cards" data-search="false"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Query Tool</strong></td><td>Where to try a query out.</td><td><a href="/setup-and-monitor/operate-and-monitor/query-your-datamart/query-tool.md">Query Tool</a></td></tr><tr><td><strong>Query API</strong></td><td>Saving and executing queries.</td><td><a href="/setup-and-monitor/operate-and-monitor/query-your-datamart/query-api.md">Query API</a></td></tr><tr><td><strong>Schema definition</strong></td><td>What makes a field queryable.</td><td><a href="/setup-and-monitor/collect-and-manage-your-data/design-your-data-model-and-schema/schema-definition.md">Schema definition</a></td></tr></tbody></table>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.mediarithmics.io/setup-and-monitor/operate-and-monitor/query-your-datamart/otql.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
