or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

authorization.mdcharts.mdcompiler.mdconditional-formatting.mddashboards.mddbt.mdee-features.mdexplore-fields.mdfilters.mdformatting.mdindex.mdmetric-queries.mdparameters.mdpivot.mdprojects-spaces.mdsql-runner.mdtemplating.mdtypes.mdutilities.mdvisualizations.mdwarehouse.md
tile.json

explore-fields.mddocs/

Explore and Field Operations

Functions for working with explores (data models) and extracting fields, dimensions, and metrics.

Overview

Explores represent data models in Lightdash, containing tables with their dimensions and metrics. These utility functions help you extract, filter, and manipulate fields from explores, build field maps for efficient lookups, and work with items (fields, table calculations, and custom dimensions).

Core Field Extraction

getFields

Gets all compiled fields (dimensions and metrics) from an explore.

function getFields(explore: Explore): CompiledField[];

Returns an array of all compiled dimensions and metrics from all tables in the explore.

Example:

import { getFields } from '@lightdash/common';

const fields = getFields(explore);
// Returns: [CompiledDimension, CompiledDimension, ..., CompiledMetric, CompiledMetric, ...]

fields.forEach(field => {
  console.log(`${field.table}.${field.name}: ${field.label}`);
});

getDimensions

Gets all compiled dimensions from an explore.

function getDimensions(explore: Explore): CompiledDimension[];

Returns an array of all compiled dimensions from all tables in the explore.

Example:

import { getDimensions, DimensionType } from '@lightdash/common';

const dimensions = getDimensions(explore);
// All dimensions across all tables

const stringDimensions = dimensions.filter(d => d.type === DimensionType.STRING);
const dateDimensions = dimensions.filter(d => d.type === DimensionType.DATE);

getMetrics

Gets all compiled metrics from an explore.

function getMetrics(explore: Explore): CompiledMetric[];

Returns an array of all compiled metrics from all tables in the explore.

Example:

import { getMetrics, MetricType } from '@lightdash/common';

const metrics = getMetrics(explore);
// All metrics across all tables

const countMetrics = metrics.filter(m => m.type === MetricType.COUNT);
const sumMetrics = metrics.filter(m => m.type === MetricType.SUM);

getVisibleFields

Gets all visible fields (non-hidden dimensions and metrics) from an explore.

function getVisibleFields(explore: Explore): CompiledField[];

Returns an array of all fields where hidden is not true.

Example:

import { getVisibleFields } from '@lightdash/common';

const visibleFields = getVisibleFields(explore);
// Only fields that should be shown in the UI

Field Lookups

findFieldByIdInExplore

Finds a specific field by its field ID within an explore.

function findFieldByIdInExplore(
  explore: Explore,
  id: FieldId
): Field | undefined;

Parameters:

  • explore: The explore to search
  • id: Field ID in the format "tableName_fieldName" (note: underscore separator, not dot)

Returns the field if found, or undefined if not found.

Note: Field IDs use underscores as separators. If a field name itself contains dots, they are replaced with double underscores. For example, a field customer_id in the customers table has ID customers_customer_id, and a field customer.id would have ID customers_customer__id.

Example:

import { findFieldByIdInExplore } from '@lightdash/common';

const field = findFieldByIdInExplore(explore, 'customers_customer_id');  // Note: underscore format
if (field) {
  console.log(`Found: ${field.label}`);
}

Field Maps and Item Maps

ItemsMap Type

The ItemsMap type is a record mapping field IDs to all queryable items in an explore.

type ItemsMap = Record<
  string,
  Field | TableCalculation | CustomDimension | Metric
>;

type Item = ItemsMap[string];

An ItemsMap contains all items that can be used in queries and visualizations, including regular fields, table calculations, and custom dimensions. Field IDs serve as keys (e.g., "customers_customer_id") and map to their full definitions.

Example:

import { type ItemsMap, getItemMap } from '@lightdash/common';

const itemsMap: ItemsMap = getItemMap(explore, additionalMetrics, tableCalculations, customDimensions);

// Access a specific item
const revenueMetric = itemsMap['customers_total_revenue'];
if (revenueMetric) {
  console.log(`${revenueMetric.label}: ${revenueMetric.table}`);
}

// Iterate through all items
Object.entries(itemsMap).forEach(([fieldId, item]) => {
  console.log(`${fieldId}: ${getItemLabel(item)}`);
});

getFieldMap

Creates a mapping of field IDs to fields (dimensions and metrics).

function getFieldMap(
  explore: Explore,
  additionalMetrics?: AdditionalMetric[]
): Record<string, CompiledField | AdditionalMetric>;

Parameters:

  • explore: The explore containing fields
  • additionalMetrics: Optional array of additional (ad-hoc) metrics to include

Returns a record mapping field IDs (e.g., "customers_total_revenue") to their field definitions.

Example:

import { getFieldMap, isMetric } from '@lightdash/common';

const fieldMap = getFieldMap(explore, additionalMetrics);
const revenueField = fieldMap['customers_total_revenue'];

if (revenueField && isMetric(revenueField)) {
  console.log(`${revenueField.label}: ${revenueField.type}`);
}

getItemMap

Creates a comprehensive mapping of all queryable items including fields, table calculations, custom dimensions, and additional metrics.

function getItemMap(
  explore: Explore,
  additionalMetrics?: AdditionalMetric[],
  tableCalculations?: TableCalculation[],
  customDimensions?: CustomDimension[]
): ItemsMap;

Parameters:

  • explore: The explore containing fields
  • additionalMetrics: Optional array of additional (ad-hoc) metrics
  • tableCalculations: Optional array of table calculations
  • customDimensions: Optional array of custom dimensions

Returns an ItemsMap containing all queryable items.

Example:

import { getItemMap, formatItemValue } from '@lightdash/common';

const itemsMap = getItemMap(
  explore,
  metricQuery.additionalMetrics,
  metricQuery.tableCalculations,
  metricQuery.customDimensions
);

// Use itemsMap for formatting and rendering
Object.entries(row).forEach(([fieldId, value]) => {
  const item = itemsMap[fieldId];
  const formatted = formatItemValue(item, value);
  console.log(`${fieldId}: ${formatted}`);
});

Extract from ItemsMap

function getDimensionsFromItemsMap(itemsMap: ItemsMap): Record<string, Dimension | CustomDimension>;
function getFilterableDimensionsFromItemsMap(itemsMap: ItemsMap): Record<string, FilterableDimension>;
function getMetricsFromItemsMap(itemsMap: ItemsMap, filter?: (value: ItemsMap[string]) => boolean): Record<string, Metric>;
function getTableCalculationsFromItemsMap(itemsMap?: ItemsMap): Record<string, TableCalculation>;

Example:

import {
  getDimensionsFromItemsMap,
  getMetricsFromItemsMap,
  getTableCalculationsFromItemsMap
} from '@lightdash/common';

const dimensions = getDimensionsFromItemsMap(itemsMap);
const metrics = getMetricsFromItemsMap(itemsMap);
const tableCalculations = getTableCalculationsFromItemsMap(itemsMap);

Field Reference Functions

Field ID Conversion

function convertFieldRefToFieldId(fieldRef: FieldRef): FieldId;
function getFieldRef(fieldId: FieldId): FieldRef;

Converts between field reference format (dot notation) and field ID format (underscore).

Important: Field IDs use underscore separators. If field name contains dots, they become double underscores:

  • Field customer_id in table customers'customers_customer_id'
  • Field customer.id in table customers'customers_customer__id' (note double underscore)

Example:

import { convertFieldRefToFieldId, getFieldRef } from '@lightdash/common';

// Convert fieldRef to fieldId
const fieldId = convertFieldRefToFieldId({ table: 'orders', field: 'total_amount' });
// Returns: 'orders_total_amount'

// Convert fieldId to fieldRef
const fieldRef = getFieldRef('orders_total_amount');
// Returns: { table: 'orders', field: 'total_amount' }

// Edge case: field name with dots
const specialId = convertFieldRefToFieldId({ table: 'customers', field: 'id.value' });
// Returns: 'customers_id__value' (double underscore)

Field Utilities

function getFieldLabel(field: Field): string;
function getItemId(item: Item): string;
function getItemLabel(item: Item): string;
function getItemLabelWithoutTableName(item: Item): string;

Example:

import { getFieldLabel, getItemLabel, getItemId } from '@lightdash/common';

const label = getFieldLabel(field);  // Returns field.label
const itemLabel = getItemLabel(item);  // Works with Field, TableCalculation, CustomDimension, etc.
const itemId = getItemId(item);  // Returns field ID for the item

Type Guards

Type guards for runtime type checking.

function isField(value: any): value is Field;
function isDimension(field: Field): field is Dimension;
function isMetric(field: Field): field is Metric;
function isCustomDimension(value: any): value is CustomDimension;
function isTableCalculation(value: any): value is TableCalculation;
function isAdditionalMetric(value: any): value is AdditionalMetric;
function isFilterableField(field: Field): field is FilterableField;

Example:

import { isDimension, isMetric, isTableCalculation } from '@lightdash/common';

const item = itemsMap['some_field_id'];

if (isDimension(item)) {
  console.log(`Dimension: ${item.type}`);
} else if (isMetric(item)) {
  console.log(`Metric: ${item.type}`);
} else if (isTableCalculation(item)) {
  console.log(`Table calculation: ${item.displayName}`);
}

Common Patterns

Date Dimension with Time Grouping

import { getDimensions, DimensionType } from '@lightdash/common';

// Find all date dimensions
const dateDimensions = getDimensions(explore).filter(d =>
  d.type === DimensionType.DATE || d.type === DimensionType.TIMESTAMP
);

// Use with time grouping suffix in queries
const query: MetricQuery = {
  exploreName: 'orders',
  dimensions: [
    'orders.created_at_day',    // Daily grouping
    'orders.created_at_month',  // Monthly grouping
  ],
  metrics: ['orders.count'],
  // ... rest of query
};

// Available suffixes: _raw, _day, _week, _month, _quarter, _year
// Note: _raw returns timestamp without grouping

Validate Query Fields Exist

import { getItemMap, itemsInMetricQuery } from '@lightdash/common';

function validateQueryFields(query: MetricQuery, explore: Explore): string[] {
  // Build complete items map
  const itemsMap = getItemMap(
    explore,
    query.additionalMetrics,
    query.tableCalculations,
    query.customDimensions
  );

  // Get all field IDs referenced in query
  const referencedFields = itemsInMetricQuery(query);

  // Find missing fields
  const missingFields = referencedFields.filter(fieldId => !itemsMap[fieldId]);

  return missingFields;
}

// Usage
const missing = validateQueryFields(metricQuery, explore);
if (missing.length > 0) {
  console.error(`Missing fields: ${missing.join(', ')}`);
}

Filter Fields by Criteria

import { getFields, isFilterableField, isNumericItem } from '@lightdash/common';

// Get all numeric, filterable fields
const numericFilterableFields = getFields(explore).filter(field =>
  isFilterableField(field) && isNumericItem(field)
);

// Get all visible dimensions
const visibleDimensions = getDimensions(explore).filter(d => !d.hidden);

// Get metrics with specific type
const countMetrics = getMetrics(explore).filter(m => m.type === MetricType.COUNT);

Edge Cases

ScenarioBehaviorSolution
Field name contains dotsDots replaced with double underscores in field IDcustomer.idcustomers_customer__id
Field not found in explorefindFieldByIdInExplore returns undefinedAlways check for undefined before using
Hidden fields in getFieldsIncluded in resultsUse getVisibleFields() to exclude hidden fields
Empty ItemsMapNo validation errors, but formatting will failAlways populate with getItemMap before formatting
Missing additional metrics in ItemsMapFormat functions can't find field definitionsInclude additionalMetrics param in getItemMap()
Table calculations not in ItemsMapWon't be accessible for formattingInclude tableCalculations param in getItemMap()