ThoughtSpot best practices

Modeling for Search & Spotter

Every setting you configure in your data model shapes what users can find — and what Spotter's AI can reason about. This reference covers every option, why it matters, and what happens when you get it wrong.

Modeling for Search

Settings that control what users see in autocomplete, how their typed queries match columns, and how ThoughtSpot generates SQL from natural language.

Modeling for Spotter

Settings that shape the AI's schema comprehension — what it reads before generating queries, what business rules it follows, and how accurately it interprets intent.

🏷️

Column name

The primary label shown in Search and read by Spotter before every query

Search + Spotter High impact

Spotter reads all column names in the model before constructing any query — like reading a schema overview first. Well-named columns let Spotter match user intent to the right column even when the user's phrasing doesn't exactly match. Spotter 3 is fully data-aware and uses names as the primary signal for column selection.

query simulator
✕ Poor column name
Column: QTY_RETAPP_P
User types "quantity sold" → No column matched. Search returns no results. Spotter generates a query against the wrong column or asks for clarification.
✓ Good column name
Column: Quantity Sold
User types "quantity sold" → Exact match. Spotter also matches "units", "how many sold", "qty" — all correctly resolved to this column.
💡Use names your business users would say aloud in a meeting. Test by asking a new team member what they'd type to find that column — if they guess wrong, rename it.
Spotter 3 improvement: well-named models produce 40–60% more accurate first-turn answers compared to models with raw database column names. Every column name is part of the AI's schema comprehension context.
📝

Description

Tooltip text for users and semantic context for Spotter's query planner

Search + Spotter

Spotter reads descriptions as inline documentation before constructing any query. A good description can encode business rules, calculation notes, and disambiguation guidance that isn't expressible in a column name alone — directly improving query accuracy without any prompting from the user.

query simulator
✕ No description
Column: Revenue (no description)
User asks "show revenue" — Spotter ambiguously picks GROSS_SALES. Finance team gets the wrong number and loses trust in the dashboard.
✓ Clear description
Description: "Net revenue after discounts and returns, before tax. Excludes intercompany. Use GROSS_SALES for pre-discount figures."
Spotter picks NET_SALES every time "revenue" is mentioned. Users hover the column and immediately understand what they're looking at.
💡Write descriptions as one-line data dictionary entries. If you wouldn't omit it from a data dictionary, don't omit it here.
↔️

Synonyms

Alternate names that resolve to the same column in Search

Search only

Different teams use different words for the same thing — Finance says "Net Sales", Sales says "Revenue", the CEO says "Top Line." Synonyms let all three resolve to the correct column without renaming it. They also catch abbreviations and legacy backend names users may type from memory.

Always add these synonym types

Backend column name

Add NET_SALES as a synonym for "Revenue" — catches users who type raw DB names

Common abbreviations

Rev, Qty, Cust, Txn — users type shortcuts constantly and expect them to work

Business unit variants

Different teams may call the same metric different things — add all known aliases

Common misspellings

If your users commonly misspell a key column, add the misspelling as a synonym

query simulator
✕ No synonyms
Column: Revenue (no synonyms)
User types "sales" → no match. Types "top line" → no match. Types "rev" → no match. User gives up and asks IT instead.
✓ Rich synonyms
Synonyms: Sales, Top Line, Net Sales, NET_SALES, Rev, Income
All six terms resolve correctly to Revenue. Users self-serve regardless of which term they use.
🗂️

Column type

ATTRIBUTE vs MEASURE — controls aggregation behavior and chart defaults

Search + SpotterHigh impact

ThoughtSpot infers MEASURE for any numeric column. This is frequently wrong. ZIP codes, order IDs, phone numbers, and product codes are numeric but should never be summed or averaged. Getting Column Type wrong causes incorrect aggregations, bad chart defaults, and Spotter answers that are confidently wrong.

Decision guide

MEASURE

Values you sum, average, or aggregate: Revenue, Quantity, Duration, Headcount. Can have a default aggregation.

ATTRIBUTE

Values you group or filter by: Region, Customer ID, ZIP Code, Order ID, Status, Phone Number — even if numeric.

query simulator
✕ Wrong type (MEASURE)
ZIP_CODE left as MEASURE
Spotter: "Sum of ZIP Code = 4,829,473,021" — completely meaningless. Chart default: bar chart of total ZIP value.
✓ Correct type (ATTRIBUTE)
ZIP_CODE set to ATTRIBUTE
Spotter groups by ZIP correctly. User can filter "sales in ZIP 90210" — works as expected. Geo map suggested automatically when geo config also set.

Additive

Whether a measure can be meaningfully summed across dimensions

Search + Spotter

MEASURES are additive by default — meaning ThoughtSpot will SUM them when aggregating across rows. For ratio metrics, percentages, and averages this produces silent, confident wrong answers. A Margin % that sums to 101% across regions will be presented without any warning unless Additive = false is set.

⚠️Rule of thumb: if a column's values don't add up to a meaningful total (percentages, ratios, rates, averages), set Additive = false. Examples: Margin %, NPS Score, Average Order Value, Conversion Rate.
query simulator
✕ Additive = true on %
Margin % — Additive = true (default)
West 32% + East 28% + North 41% = Total: 101% margin. Confidently presented. Finance raises an incident.
✓ Additive = false
Margin % — Additive = false
Spotter uses weighted average. Total shows 33.4% blended margin. Correct, auditable, consistent with finance reports.
ƒ

Default aggregation

The fallback aggregation when no keyword is specified

Search + Spotter

When a user types "Revenue by Region" without specifying SUM or AVERAGE, ThoughtSpot uses the column's default aggregation. Setting this correctly means the most common query pattern returns the right answer with zero extra keywords — and tells Spotter which aggregation to assume when constructing queries autonomously.

Recommended defaults by metric type

SUM

Revenue, Quantity, Spend, Units — any value that should be totaled across rows

COUNT

Transactions, Orders, Events — counting distinct occurrences of something

AVERAGE

Rate metrics: Avg Order Value, NPS, Duration — summing these produces nonsense

MIN / MAX

Useful for date ranges, price bounds, or any column where extremes are more meaningful than totals

NONE

All ATTRIBUTEs — they are grouped and filtered, never aggregated

🔍

Index type

Controls whether column values appear as suggestions and can be matched by Spotter

Search + SpotterSecurity sensitive

Spotter uses indexed values to resolve ambiguous user input to actual data values. If a State column is indexed, Spotter can match "Pacific Northwest" to the specific state codes. Without indexing, Spotter must guess — and may generate a WHERE clause with values that don't exist in your data.

Index type options

DEFAULT

Indexes all column values. Best for low-to-medium cardinality: Region, Product Category, Status, Account Name.

PREFIX_ONLY

Auto-applied to strings longer than 50 characters. Matches only from the start of values. Use only for structured short values.

DONT_INDEX

No value suggestions. Use for sensitive columns, very high-cardinality free text, or ABAC/RLS-restricted fields.

🔒Embedded security note: The suggestion index is built independently of ABAC/RLS runtime token filters. A user restricted by a token variable may still see unauthorized values in autocomplete. Use DONT_INDEX on sensitive columns (dealer_id, customer_segment) or apply an RLS rule at the model level so the index itself is filtered.
👁️

Hidden

Remove columns from Search and Spotter without deleting them from the model

Search + Spotter

Hidden columns are excluded from the schema context Spotter reads before generating queries. This reduces schema noise — a Spotter reasoning over a clean 30-column model performs significantly better than one parsing 80 columns where half are internal plumbing. Hide aggressively: expose only what users actually query.

Good candidates for hiding

Join keys

Foreign keys like PRODUCT_ID, CUSTOMER_FK — users should never search on raw key columns

Formula inputs

Raw columns that feed calculated fields — hide the input, expose only the formula result

RLS driver columns

Columns used in security rule formulas — must be hidden from direct user access

Technical flags

IS_DELETED, CREATED_BY_SYSTEM, ETL_BATCH_ID — internal housekeeping columns with no business value

⚠️Hidden is a UI control only — it does not restrict data access. For actual row-level security in embedded apps, use RLS rules or ABAC token variable values, not Hidden alone.
💬

Suggest values in Search

Whether column values appear as dropdown suggestions as users type

Search onlyModel level only

Controls whether values for a column populate the Search bar dropdown as users type. Only available at the Model level (not Table level). Disable for very high-cardinality columns where suggestions would be overwhelming and slow — transaction IDs, timestamps, free-text fields. Enable for dimensions users commonly filter on.

query simulator
✕ Suggestions on high-cardinality
Transaction ID — suggest values: ON
User starts typing → dropdown shows millions of GUIDs. Slow, useless, and clutters the search experience. Users learn to avoid Search entirely.
✓ Suggestions on useful column
Order Status — suggest values: ON
User types "pend" → sees "Pending", "Pending Review" → correct filter applied in one click. Reduces mistyped values to near zero.
Aa

Data value case

Tells ThoughtSpot how data is stored to avoid costly SQL case-conversion functions

Search onlyPerformance impact

ThoughtSpot is case-insensitive by default, but some databases are not. Without this setting, ThoughtSpot wraps filter values in LOWER() or UPPER() — which can prevent index usage in Snowflake, Redshift, and BigQuery, causing full table scans on large fact tables. Setting the correct casing eliminates this overhead.

Options

ALL UPPER CASE

Data is stored uppercase. ThoughtSpot uppercases user input before comparison — no LOWER() needed in SQL.

ALL LOWER CASE

Data stored lowercase. ThoughtSpot lowercases user input. Clean SQL, no function wrapping.

MIXED

ThoughtSpot applies LOWER() to both sides. Correct but may impact query performance on large tables.

-- Without casing setting (MIXED): slow on large tables WHERE LOWER("PRODUCTTYPE") = 'jackets' -- With ALL LOWER CASE set: index-friendly WHERE "PRODUCTTYPE" = 'jackets'
⚠️Audit your ETL pipeline before setting this. Inconsistent source data (some rows "Jackets", some "JACKETS") will cause missed filter matches — users get zero results for correct queries.
📅

Calendar type

How relative date keywords like "this quarter" and "YTD" are resolved

Search + Spotter

Relative date keywords are resolved against the calendar type assigned to the date column. If your fiscal year starts April 1 but you use Gregorian calendar, "Q1" returns January–March — wrong for every fiscal report. This is the single most common cause of "why is my quarter number off?" questions.

Calendar options

Gregorian (default)

Jan 1–Dec 31 year, weeks start Monday. Correct for calendar-year businesses.

Fiscal

Custom year start/end month. Critical if your Q1 ≠ January. Configure the start month per connection.

Custom

Arbitrary period boundaries: retail 4-4-5, broadcast calendar, or any non-standard period structure.

query simulator — fiscal year starting April 1
✕ Gregorian calendar
User query: "sales this quarter" (asked in May)
Returns April–June (Gregorian Q2). Business fiscal Q1 is also Apr–Jun but labeled Q1. Numbers don't match any finance report. Trust eroded.
✓ Fiscal calendar set
User query: "sales this quarter" (asked in May)
Returns fiscal Q1 (April–June). Matches every other business report. Relative keywords "last year", "YTD" all align correctly to fiscal boundaries.
⚠️Per-user timezone is separate — set via POST /users/{id}/update with extended_properties: {"preferredTimezone": "America/New_York"}. It cannot be passed via variable_values in the token API — that causes a type error.
🗺️

Geo config

Enables geographic map visualizations from location columns

Search + Spotter

Without Geo Config, ThoughtSpot treats a column named "State" as just another string attribute and defaults to a table or bar chart. With the correct Geo Config type set, Search and Spotter automatically generate geo maps when a location column is referenced — no extra keywords needed from the user.

Geo config types

Country / State / City

Named place columns — ThoughtSpot resolves the name to its boundary automatically

ZIP / Postal code

ZIP-level mapping for US and international postal codes

Latitude + Longitude

Exact coordinate pairs for precise point mapping — requires two separate columns both configured

Custom region

User-defined geographic groupings that don't map to standard boundaries

query simulator
✕ No geo config
User: "revenue by state"
Returns a bar chart or table. Map never suggested. User has to manually change chart type — most won't bother.
✓ Geo config = State
User: "revenue by state"
Geo map automatically generated and recommended as the default visualization. Spotter also selects map as preferred chart type for location-based queries.

Attribution dimension

Controls chasm trap resolution when querying across two fact tables

Search + SpotterSchema design

A chasm trap occurs when two fact tables (Sales and Budget) share a common dimension (Customer) but have no direct join between them. When a user asks "Sales and Budget by Customer", ThoughtSpot must determine which shared dimensions are valid join bridges. Attribution Dimension controls this — set incorrectly it silently inflates or distorts results through row multiplication.

chasm trap — Sales fact + Budget fact, shared Customer and Date dimensions
✕ Date = Attribution YES
Date dimension set as Attribution = YES
ThoughtSpot bridges Sales and Budget via Date. Every Sales row multiplied by every Budget row that shares the same date. Revenue fans out to 10× actual value. Confidently wrong.
✓ Customer = Attribution YES, Date = NO
Customer = YES (causal), Date = NO (lookup)
Sales and Budget correctly joined via Customer. "Sales and Budget by Customer" returns correct figures. Date used as a filter only, not as a bridge.
⚠️Set Attribution on DIMENSION tables only, never on fact tables. Always test chasm trap queries after modeling — verify "Fact A + Fact B by [dimension]" produces expected row counts before publishing to users.
🧠

Data model instructions

Global rules every Spotter conversation on this model inherits automatically

Spotter 2 + 3 New — 26.2.0.cl+ Highest leverage

Model Instructions are the single highest-leverage Spotter modeling action. They encode business logic at the model level so every conversation inherits it automatically — no per-user setup, no repeated prompting needed. This is where you capture the "rules everyone knows but no one types" that determine whether Spotter's answers are business-correct or just technically valid SQL.

High-impact instruction examples

Metric definitions

"Revenue means net revenue (NET_SALES). Do not use GROSS_SALES unless explicitly asked."

Default filters

"Always exclude cancelled orders (STATUS = 'CANCELLED') unless the user explicitly asks to include them."

Date defaults

"When no time period is specified, default to the current fiscal year."

Column preference

"When asked about 'region', use SALES_REGION, not SHIPPING_REGION."

Aggregation rules

"Margin % should always be calculated as a weighted average, never summed."

Hierarchy guidance

"Product hierarchy: Category → Subcategory → Product. Use Category for high-level queries."

spotter conversation simulator
✕ No model instructions
User: "show me revenue last quarter"
Spotter picks GROSS_SALES (first revenue-like column). Includes cancelled orders. Uses calendar quarter, not fiscal. Finance rejects the number in the board deck.
✓ Model instructions set
User: "show me revenue last quarter"
Spotter uses NET_SALES, filters out cancelled orders, uses fiscal Q3. Answer matches finance report exactly. Zero follow-up questions needed.
Column names tell Spotter what exists. Descriptions explain individual columns. Model Instructions tell Spotter how to use them correctly — encoding the business rules that turn technically valid SQL into business-correct answers. Think of coaching feedback from users as signals for which instructions to add next.