> ## Documentation Index
> Fetch the complete documentation index at: https://docs.datasnap.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Consulta de Registros

> Execute consultas complexas similares ao SQL contra os dados do schema armazenados na Datasnap Big Data com suporte a filtragem, agrupamento, ordenação e paginação.

## Interface Gráfica Disponível

<Info>
  **Para usuários iniciantes**: Se você não sabe como usar este endpoint ou prefere uma interface visual, temos uma **tela perfeita** para realizar essas consultas! Você pode executar todas essas consultas diretamente pelo **app DataSnap** de forma intuitiva e visual, sem precisar conhecer a sintaxe da API.
</Info>

<Tip>
  **Acesse o app DataSnap**: Faça login em [app.datasnap.cloud](https://app.datasnap.cloud) e navegue até a seção de consultas do seu schema para usar a interface gráfica amigável.
</Tip>

## Autenticação

<Info>
  Este endpoint requer autenticação. Inclua seu token Bearer no cabeçalho Authorization.
</Info>

```bash theme={null}
Authorization: Bearer SEU_TOKEN_AQUI
```

## Parâmetros de Caminho

<ParamField path="slug" type="string" required>
  O slug do schema
</ParamField>

## Corpo da Requisição

<ParamField body="select" type="array" required>
  Array de nomes de colunas ou expressões para selecionar. O uso de `*` não é permitido.

  <Expandable title="Exemplos">
    * `["nome", "idade", "cidade"]`
    * `["cidade", "count(*) as total_usuarios"]`
    * `["avg(idade) as idade_media", "max(salario) as salario_max"]`
  </Expandable>
</ParamField>

<ParamField body="event_from" type="string" required placeholder="YYYY-MM-DD">
  Data de início para a janela de consulta (obrigatório para performance e particionamento).
</ParamField>

<ParamField body="event_to" type="string" required placeholder="YYYY-MM-DD">
  Data de fim para a janela de consulta (obrigatório para performance e particionamento).
</ParamField>

<ParamField body="where" type="array">
  Array de condições de filtro para aplicar à consulta (além do período obrigatório).

  <Expandable title="Estrutura do Objeto Condição">
    <ParamField body="field" type="string" required>
      Nome do campo para filtrar
    </ParamField>

    <ParamField body="op" type="string" required>
      Operador de comparação. Opções: `=`, `!=`, `>`, `<`, `>=`, `<=`, `like`, `not like`, `in`, `not in`, `between`, `is null`, `is not null`
    </ParamField>

    <ParamField body="value" type="mixed">
      Valor para comparar. Para operações `in`/`not in`, forneça um array. Para `between`, forneça array com `[de, até]`. Para `is null`/`is not null`, isso pode ser omitido.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="group_by" type="array">
  Array de nomes de colunas para agrupar
</ParamField>

<ParamField body="order_by" type="array">
  Array de especificações de ordenação.

  <Expandable title="Estrutura do Objeto Ordenação">
    <ParamField body="field" type="string" required>
      Nome do campo para ordenar
    </ParamField>

    <ParamField body="direction" type="string">
      Direção da ordenação. Opções: `asc`, `desc`, `ASC`, `DESC` (padrão: `asc`)
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="limit" type="integer" default="100">
  Número máximo de registros para retornar (1-10000)
</ParamField>

<ParamField body="offset" type="integer" default="0">
  Número de registros para pular (não pode ser usado com `page_token`)
</ParamField>

<ParamField body="page_token" type="string">
  Cursor codificado em Base64 para paginação. Não pode ser usado com `offset`.
</ParamField>

<ParamField body="format" type="string" default="json_compact">
  Formato da resposta. Opções: `json`, `json_compact`, `json_compact_strings`, `jsonl`
</ParamField>

<ParamField body="include_meta" type="boolean" default="true">
  Se deve incluir metadados na resposta
</ParamField>

## Resposta

O formato da resposta depende do parâmetro `format`:

### Formato JSON (`json`)

<ResponseField name="data" type="array">
  Array de objetos, onde cada objeto representa uma linha com nomes de colunas como chaves
</ResponseField>

<ResponseField name="meta" type="object">
  Metadados da consulta incluindo informações das colunas
</ResponseField>

<ResponseField name="statistics" type="object">
  Estatísticas de execução da consulta (tempo decorrido, linhas lidas, bytes lidos)
</ResponseField>

### Formato JSON Compacto (`json_compact`)

<ResponseField name="meta" type="array">
  Array de objetos de metadados de colunas com propriedades `name` e `type`
</ResponseField>

<ResponseField name="data" type="array">
  Array de arrays, onde cada array interno representa uma linha com valores na mesma ordem das colunas meta
</ResponseField>

<ResponseField name="statistics" type="object">
  Estatísticas de execução da consulta
</ResponseField>

### Formato JSONL (`jsonl`)

Retorna cada linha como um objeto JSON separado em sua própria linha (JSON delimitado por quebras de linha).

<RequestExample>
  ```bash Consulta Simples theme={null}
  curl -X POST \
    "https://api.datasnap.cloud/api/v1/schemas/meu-schema/query" \
    -H "Authorization: Bearer SEU_TOKEN_AQUI" \
    -H "Content-Type: application/json" \
    -d '{
      "select": ["nome", "idade", "cidade"],
      "event_from": "2024-01-01",
      "event_to": "2024-12-31",
      "where": [
        {"field": "idade", "op": ">", "value": 18},
        {"field": "cidade", "op": "in", "value": ["São Paulo", "Rio de Janeiro"]}
      ],
      "order_by": [
        {"field": "nome", "direction": "asc"}
      ],
      "limit": 50
    }'
  ```

  ```bash Consulta com Agregação theme={null}
  curl -X POST \
    "https://api.datasnap.cloud/api/v1/schemas/meu-schema/query" \
    -H "Authorization: Bearer SEU_TOKEN_AQUI" \
    -H "Content-Type: application/json" \
    -d '{
      "select": ["cidade", "count(*) as total_usuarios", "avg(idade) as idade_media"],
      "event_from": "2024-01-01",
      "event_to": "2024-12-31",
      "where": [
        {"field": "idade", "op": "between", "value": [18, 65]}
      ],
      "group_by": ["cidade"],
      "order_by": [
        {"field": "total_usuarios", "direction": "desc"}
      ],
      "limit": 20
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    'https://api.datasnap.cloud/api/v1/schemas/meu-schema/query',
    {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer SEU_TOKEN_AQUI',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        select: ['nome', 'idade', 'cidade'],
        event_from: '2024-01-01',
        event_to: '2024-12-31',
        where: [
          { field: 'idade', op: '>', value: 18 },
          { field: 'status', op: '=', value: 'ativo' }
        ],
        order_by: [
          { field: 'criado_em', direction: 'desc' }
        ],
        limit: 100
      })
    }
  );

  const data = await response.json();
  ```

  ```python Python theme={null}
  import requests
  import json

  url = "https://api.datasnap.cloud/api/v1/schemas/meu-schema/query"
  headers = {
      "Authorization": "Bearer SEU_TOKEN_AQUI",
      "Content-Type": "application/json"
  }

  payload = {
      "select": ["nome", "idade", "cidade"],
      "event_from": "2024-01-01",
      "event_to": "2024-12-31",
      "where": [
          {"field": "idade", "op": ">", "value": 18},
          {"field": "status", "op": "=", "value": "ativo"}
      ],
      "order_by": [
          {"field": "criado_em", "direction": "desc"}
      ],
      "limit": 100
  }

  response = requests.post(url, headers=headers, data=json.dumps(payload))
  data = response.json()
  ```

  ```bash Paginação com Cursor theme={null}
  curl -X POST \
    "https://api.datasnap.cloud/api/v1/schemas/meu-schema/query" \
    -H "Authorization: Bearer SEU_TOKEN_AQUI" \
    -H "Content-Type: application/json" \
    -d '{
      "select": ["id", "nome", "criado_em"],
      "order_by": [
        {"field": "criado_em", "direction": "desc"}
      ],
      "limit": 100,
      "page_token": "eyJjcmVhdGVkX2F0IjoiMjAyNC0wOC0xNVQxMDozMDowMFoiLCJpZCI6MTIzZQ=="
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json Resposta em Formato JSON theme={null}
  {
    "data": [
      {
        "nome": "João Silva",
        "idade": 30,
        "cidade": "São Paulo"
      },
      {
        "nome": "Maria Santos",
        "idade": 25,
        "cidade": "Rio de Janeiro"
      }
    ],
    "meta": {
      "columns": [
        {"name": "nome", "type": "String"},
        {"name": "idade", "type": "UInt32"},
        {"name": "cidade", "type": "String"}
      ]
    },
    "statistics": {
      "elapsed": 0.003,
      "rows_read": 1000,
      "bytes_read": 50000
    }
  }
  ```

  ```json Resposta em Formato JSON Compacto theme={null}
  {
    "meta": [
      {"name": "nome", "type": "String"},
      {"name": "idade", "type": "UInt32"},
      {"name": "cidade", "type": "String"}
    ],
    "data": [
      ["João Silva", 30, "São Paulo"],
      ["Maria Santos", 25, "Rio de Janeiro"]
    ],
    "statistics": {
      "elapsed": 0.003,
      "rows_read": 1000,
      "bytes_read": 50000
    }
  }
  ```

  ```text Resposta em Formato JSONL theme={null}
  {"nome":"João Silva","idade":30,"cidade":"São Paulo"}
  {"nome":"Maria Santos","idade":25,"cidade":"Rio de Janeiro"}
  ```

  ```json Resposta de Erro (400) theme={null}
  {
    "error": "Schema sem tabela Datasnap Big Data vinculada."
  }
  ```

  ```json Resposta de Erro (422) theme={null}
  {
    "error": "Select inválido. Utilize colunas específicas; uso de * não é permitido."
  }
  ```

  ```json Resposta de Erro (401) theme={null}
  {
    "error": "Não autenticado."
  }
  ```
</ResponseExample>

## Códigos de Erro

<ResponseField name="200" type="Success">
  Consulta executada com sucesso
</ResponseField>

<ResponseField name="400" type="Error">
  Requisição inválida - Schema sem tabela Datasnap Big Data ou credenciais ausentes
</ResponseField>

<ResponseField name="401" type="Error">
  Não autorizado - Token de autenticação inválido ou ausente
</ResponseField>

<ResponseField name="422" type="Error">
  Erro de validação ou parâmetros de consulta inválidos
</ResponseField>

<ResponseField name="500" type="Error">
  Erro interno do servidor
</ResponseField>

## Exemplos de Consulta

### Filtragem Básica

```json theme={null}
{
  "select": ["nome", "email", "criado_em"],
  "event_from": "2024-01-01",
  "event_to": "2024-12-31",
  "where": [
    {"field": "status", "op": "=", "value": "ativo"},
    {"field": "criado_em", "op": ">", "value": "2024-01-01"}
  ],
  "limit": 100
}
```

### Filtragem Avançada com IN e BETWEEN

```json theme={null}
{
  "select": ["nome_produto", "preco", "categoria"],
  "event_from": "2024-01-01",
  "event_to": "2024-12-31",
  "where": [
    {"field": "categoria", "op": "in", "value": ["eletrônicos", "livros"]},
    {"field": "preco", "op": "between", "value": [10, 100]},
    {"field": "estoque", "op": "is not null"}
  ]
}
```

### Agregação com Agrupamento

```json theme={null}
{
  "select": ["categoria", "count(*) as total_produtos", "avg(preco) as preco_medio"],
  "event_from": "2024-01-01",
  "event_to": "2024-12-31",
  "group_by": ["categoria"],
  "order_by": [
    {"field": "total_produtos", "direction": "desc"}
  ]
}
```

### Consulta Complexa com Múltiplas Condições

```json theme={null}
{
  "select": ["id_usuario", "nome", "ultimo_login", "total_pedidos"],
  "event_from": "2024-01-01",
  "event_to": "2024-12-31",
  "where": [
    {"field": "ultimo_login", "op": ">=", "value": "2024-01-01"},
    {"field": "total_pedidos", "op": ">", "value": 5},
    {"field": "status", "op": "!=", "value": "suspenso"}
  ],
  "order_by": [
    {"field": "total_pedidos", "direction": "desc"},
    {"field": "ultimo_login", "direction": "desc"}
  ],
  "limit": 50
}
```

## Paginação

### Paginação Baseada em Offset

```json theme={null}
{
  "select": ["id", "nome"],
  "event_from": "2024-01-01",
  "event_to": "2024-12-31",
  "order_by": [{"field": "id", "direction": "asc"}],
  "limit": 25,
  "offset": 100
}
```

### Paginação Baseada em Cursor (Recomendado)

Para melhor performance com grandes conjuntos de dados, use paginação baseada em cursor:

```json theme={null}
{
  "select": ["id", "nome", "criado_em"],
  "event_from": "2024-01-01",
  "event_to": "2024-12-31",
  "order_by": [{"field": "criado_em", "direction": "desc"}],
  "limit": 25,
  "page_token": "base64_encoded_cursor"
}
```

<Warning>
  Não é possível usar `offset` e `page_token` juntos. Escolha um método de paginação.
</Warning>

## Formatos de Resposta

### Escolhendo o Formato Certo

* **`json`**: Melhor para conjuntos de resultados pequenos a médios onde você precisa de colunas nomeadas
* **`json_compact`**: Mais eficiente para grandes conjuntos de resultados, reduz o tamanho da resposta
* **`json_compact_strings`**: Todos os valores retornados como strings, útil para tipagem consistente
* **`jsonl`**: Melhor para streaming de grandes conjuntos de resultados, um objeto JSON por linha

## Dicas e Melhores Práticas

<Tip>
  Sempre especifique nomes de colunas explícitos no array `select`. O uso de `*` não é permitido por razões de segurança e performance.
</Tip>

<Tip>
  Use o formato `json_compact` para grandes conjuntos de resultados para reduzir o tamanho da resposta e melhorar a performance.
</Tip>

<Tip>
  Prefira paginação baseada em cursor (`page_token`) ao invés de paginação baseada em offset para grandes conjuntos de dados.
</Tip>

<Warning>
  Ao usar funções de agregação no `select`, alguns campos ORDER BY (especialmente campos do sistema com prefixo underscore) podem ser automaticamente filtrados.
</Warning>
