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

# Infer and Apply Table Indexes

> Use the table index endpoints to inspect inferred index settings and generate an updated Pinot table config.

Use `POST /tables/inferIndexes` and `POST /tables/applyIndexes` to build an index-editing workflow around a Pinot table config and schema.

* `inferIndexes` converts the table config into the index-grid shape used by StarTree tooling.
* `applyIndexes` converts an edited index-grid shape back into an updated table config.

These endpoints are configuration helpers. They do not create a table, update a table, rebuild segments, or reload data.

<Warning>
  `applyIndexes` returns `updatedTableConfig`. Persist the returned table config with the normal table update flow, then reload or regenerate affected segments when the changed index type requires segment changes.
</Warning>

## Endpoints

```http theme={null}
POST /tables/inferIndexes
Content-Type: application/json
```

```http theme={null}
POST /tables/applyIndexes
Content-Type: application/json
```

## When to Use These Endpoints

Use these endpoints when you want to:

* Build an index editor that starts from an existing table config and schema.
* Normalize older table configs into the field-config based index model.
* Convert dictionary-disabled fields into `RAW` column encoding.
* Edit per-column index settings without hand-writing the full `fieldConfigList`.
* Preserve sorted columns and star-tree index configs while round-tripping through an index UI.

## Infer Existing Indexes

`inferIndexes` accepts a table config and schema. The response contains per-column index settings, column encodings, sorted columns, star-tree index configs, and an updated table config.

```json theme={null}
{
  "tableConfig": {
    "tableName": "orders_OFFLINE",
    "tableType": "OFFLINE",
    "segmentsConfig": {
      "schemaName": "orders"
    },
    "fieldConfigList": [
      {
        "name": "orderId",
        "encodingType": "RAW",
        "indexes": {
          "inverted": {}
        }
      }
    ],
    "tableIndexConfig": {
      "sortedColumn": ["eventTimeMs"]
    }
  },
  "schema": {
    "schemaName": "orders",
    "dimensionFieldSpecs": [
      {"name": "orderId", "dataType": "STRING"},
      {"name": "customerId", "dataType": "STRING"},
      {"name": "status", "dataType": "STRING"}
    ],
    "metricFieldSpecs": [
      {"name": "amount", "dataType": "DOUBLE"}
    ],
    "dateTimeFieldSpecs": [
      {
        "name": "eventTimeMs",
        "dataType": "TIMESTAMP",
        "format": "1:MILLISECONDS:EPOCH",
        "granularity": "1:MILLISECONDS"
      }
    ]
  }
}
```

Example request:

```bash theme={null}
curl -sS -X POST "https://<controller-host>:9000/tables/inferIndexes" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  --data @infer-indexes-request.json | jq
```

Example response shape:

```json theme={null}
{
  "indexConfigMap": {
    "orderId": {
      "dictionary": {
        "disabled": true
      },
      "inverted": {}
    },
    "status": {
      "dictionary": {},
      "inverted": {}
    }
  },
  "starTreeIndexConfigs": [],
  "sortedColumns": ["eventTimeMs"],
  "columnEncodings": {
    "orderId": "RAW"
  },
  "updatedTableConfig": {
    "tableName": "orders_OFFLINE",
    "tableType": "OFFLINE"
  }
}
```

## Apply Edited Indexes

`applyIndexes` accepts the table config, schema, and edited index settings. The response contains an updated table config with the requested index changes applied.

Required request fields:

| Field                  | Required | Description                                                          |
| ---------------------- | -------- | -------------------------------------------------------------------- |
| `tableConfig`          | Yes      | Base Pinot table config to update.                                   |
| `schema`               | Yes      | Schema used to validate the resulting table config.                  |
| `indexConfigMap`       | Yes      | Per-column map of index type IDs to index config objects.            |
| `columnEncodings`      | Yes      | Per-column encoding map. Columns not listed default to `DICTIONARY`. |
| `sortedColumns`        | No       | Sorted-column list to write to `tableIndexConfig.sortedColumn`.      |
| `starTreeIndexConfigs` | No       | Star-tree index configs to write to the table indexing config.       |

Example request:

```json theme={null}
{
  "tableConfig": {
    "tableName": "orders_OFFLINE",
    "tableType": "OFFLINE",
    "segmentsConfig": {
      "schemaName": "orders"
    },
    "tableIndexConfig": {}
  },
  "schema": {
    "schemaName": "orders",
    "dimensionFieldSpecs": [
      {"name": "orderId", "dataType": "STRING"},
      {"name": "customerId", "dataType": "STRING"},
      {"name": "status", "dataType": "STRING"}
    ],
    "metricFieldSpecs": [
      {"name": "amount", "dataType": "DOUBLE"}
    ],
    "dateTimeFieldSpecs": [
      {
        "name": "eventTimeMs",
        "dataType": "TIMESTAMP",
        "format": "1:MILLISECONDS:EPOCH",
        "granularity": "1:MILLISECONDS"
      }
    ]
  },
  "indexConfigMap": {
    "orderId": {
      "inverted": {},
      "range": null
    },
    "status": {
      "inverted": {}
    },
    "customerId": {
      "bloom": {
        "fpp": 0.01,
        "maxSizeInBytes": 1048576
      }
    }
  },
  "columnEncodings": {
    "orderId": "RAW",
    "customerId": "DICTIONARY",
    "status": "DICTIONARY"
  },
  "sortedColumns": ["eventTimeMs"],
  "starTreeIndexConfigs": []
}
```

Example request:

```bash theme={null}
curl -sS -X POST "https://<controller-host>:9000/tables/applyIndexes" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  --data @apply-indexes-request.json | jq '.updatedTableConfig'
```

Example response shape:

```json theme={null}
{
  "updatedTableConfig": {
    "tableName": "orders_OFFLINE",
    "tableType": "OFFLINE",
    "fieldConfigList": [
      {
        "name": "orderId",
        "encodingType": "RAW",
        "indexes": {
          "inverted": {}
        }
      },
      {
        "name": "customerId",
        "encodingType": "DICTIONARY",
        "indexes": {
          "bloom": {
            "fpp": 0.01,
            "maxSizeInBytes": 1048576
          }
        }
      },
      {
        "name": "status",
        "encodingType": "DICTIONARY",
        "indexes": {
          "inverted": {}
        }
      }
    ],
    "tableIndexConfig": {
      "sortedColumn": ["eventTimeMs"]
    }
  }
}
```

## Round-Trip Workflow

1. Fetch the current table config and schema.
2. Call `POST /tables/inferIndexes`.
3. Present `indexConfigMap`, `columnEncodings`, `sortedColumns`, and `starTreeIndexConfigs` to the user or automation.
4. Edit the desired index settings.
5. Call `POST /tables/applyIndexes` with the original table config, schema, and edited index data.
6. Review `updatedTableConfig`.
7. Persist `updatedTableConfig` with the table update API.
8. Reload or regenerate segments when the changed index type requires segment materialization.

## Field Behavior

| Field                  | Behavior                                                                                                                                    |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `indexConfigMap`       | Keys are column names. Values are maps from index type IDs, such as `inverted`, `bloom`, `range`, or `dictionary`, to index config objects. |
| `columnEncodings`      | Controls each column's `encodingType`. Missing columns default to `DICTIONARY`.                                                             |
| `sortedColumns`        | Replaces the table config's sorted-column list.                                                                                             |
| `starTreeIndexConfigs` | Replaces the table config's star-tree index config list.                                                                                    |
| `updatedTableConfig`   | Output table config after normalization or application. You must explicitly save it.                                                        |

## Dictionary and Raw Encoding Notes

`applyIndexes` keeps dictionary configuration and column encoding consistent:

* A column with `RAW` encoding does not keep a dictionary index for Pinot local tables.
* Dictionary-disabled field configs are normalized to `RAW` encoding.
* External table configs keep dictionary metadata that is needed by the external table flow.

## Troubleshooting

| Symptom                                        | Cause                                                                  | Fix                                                                                       |
| ---------------------------------------------- | ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| `table config in request can't be null`        | Missing `tableConfig`.                                                 | Include the table config in the request body.                                             |
| `schema config in request can't be null`       | Missing `schema`.                                                      | Include the schema in the request body.                                                   |
| `column encodings in request can't be null`    | Missing `columnEncodings` on `applyIndexes`.                           | Send the `columnEncodings` map returned by `inferIndexes`, updated with any user changes. |
| The table does not change after `applyIndexes` | The endpoint only returns a config.                                    | Persist `updatedTableConfig` with the table update API.                                   |
| Query plans do not use a newly enabled index   | Existing segments were not rebuilt or reloaded with the changed index. | Reload or regenerate affected segments after saving the table config.                     |
