Implementation:Langfuse Langfuse ClickHouse Filter
| Knowledge Sources | |
|---|---|
| Domains | ClickHouse, Query Building |
| Last Updated | 2026-02-14 00:00 GMT |
Overview
Provides a type-safe filter class hierarchy for constructing parameterized ClickHouse WHERE clauses, along with a FilterList container that composes multiple filters into a single AND-joined query.
Description
This module implements the filter abstraction layer for ClickHouse queries in Langfuse. It defines a Filter interface and a set of concrete filter classes, each generating parameterized ClickHouse SQL fragments with unique parameter names (using random suffixes to avoid collisions):
StringFilter: Handles string comparisons with operators=,contains,does not contain,starts with,ends with.NumberFilter: Handles numeric comparisons (=,<,<=,>,>=,!=) with configurable ClickHouse type (defaultDecimal64(12)).DateTimeFilter: Handles date/time range comparisons usingDateTime64(3)with millisecond precision.StringOptionsFilter: Handles IN/NOT IN queries for multi-select string values.CategoryOptionsFilter: Handles hierarchical category filtering usinghasAny/NOT hasAnywith flattenedkey:valuestrings.StringObjectFilter: Handles key-value filtering on Map columns (observations/traces) or Array columns (events table) for metadata filtering.ArrayOptionsFilter: Handles array column filtering withany of,none of, andall ofoperators usinghasAny/hasAll.NullFilter: Handles IS NULL/IS NOT NULL checks.NumberObjectFilter: Handles numeric filtering within map/tuple arrays usingarrayFilter.BooleanFilter: Handles boolean equality checks.
The FilterList class aggregates multiple filters, providing collection operations (push, find, filter, map, some, forEach) and an apply() method that joins all filters with AND and merges parameters.
Usage
Use these filter classes when building ClickHouse queries throughout the Langfuse query layer. Construct individual filters from user-provided filter states, add them to a FilterList, and call apply() to get the combined WHERE clause and parameters for the query.
Code Reference
Source Location
- Repository: Langfuse
- File: packages/shared/src/server/queries/clickhouse-sql/clickhouse-filter.ts
- Lines: 1-516
Signature
export type ClickhouseOperator = (typeof filterOperators)[keyof typeof filterOperators][number] | "!=";
export interface Filter {
apply(): { query: string; params: Record<string, any> };
clickhouseTable: string;
tablePrefix?: string;
operator: ClickhouseOperator;
field: string;
}
export class StringFilter implements Filter { ... }
export class NumberFilter implements Filter { ... }
export class DateTimeFilter implements Filter { ... }
export class StringOptionsFilter implements Filter { ... }
export class CategoryOptionsFilter implements Filter { ... }
export class StringObjectFilter implements Filter { ... }
export class ArrayOptionsFilter implements Filter { ... }
export class NullFilter implements Filter { ... }
export class NumberObjectFilter implements Filter { ... }
export class BooleanFilter implements Filter { ... }
export class FilterList {
constructor(filters?: Filter[]);
push(...filter: Filter[]): void;
find(predicate: (filter: Filter) => boolean): Filter | undefined;
filter(predicate: (filter: Filter) => boolean): FilterList;
map(predicate: (filter: Filter) => Filter): FilterList;
some(predicate: (filter: Filter) => boolean): boolean;
forEach(callback: (filter: Filter) => void): void;
length(): number;
apply(): { query: string; params: Record<string, any> };
}
Import
import {
FilterList,
StringFilter,
NumberFilter,
DateTimeFilter,
StringOptionsFilter,
ArrayOptionsFilter,
StringObjectFilter,
NullFilter,
} from "@langfuse/shared/src/server/queries/clickhouse-sql/clickhouse-filter";
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| clickhouseTable | string | Yes | The ClickHouse table name this filter applies to (e.g., "events", "traces", "observations") |
| field | string | Yes | The column name to filter on |
| operator | ClickhouseOperator | Yes | The comparison operator (=, <, >, contains, any of, etc.) |
| value | string / number / Date / boolean / string[] | Yes | The filter value(s) appropriate for the filter type |
| tablePrefix | string | No | Optional table alias prefix (e.g., "e", "t") for qualified column references |
| key | string | No | For StringObjectFilter/NumberObjectFilter/CategoryOptionsFilter: the map key to filter on |
Outputs
| Name | Type | Description |
|---|---|---|
| query | string | A parameterized ClickHouse SQL WHERE clause fragment |
| params | Record<string, any> | Parameter values keyed by unique parameter names for safe query interpolation |
Usage Examples
import {
FilterList,
StringFilter,
DateTimeFilter,
ArrayOptionsFilter,
} from "@langfuse/shared/src/server/queries/clickhouse-sql/clickhouse-filter";
// Build a filter list
const filters = new FilterList();
filters.push(
new StringFilter({
clickhouseTable: "events",
field: "name",
operator: "contains",
value: "chat",
tablePrefix: "e",
}),
new DateTimeFilter({
clickhouseTable: "events",
field: "start_time",
operator: ">=",
value: new Date("2024-01-01"),
tablePrefix: "e",
}),
new ArrayOptionsFilter({
clickhouseTable: "events",
field: "tags",
operator: "any of",
values: ["production", "important"],
tablePrefix: "e",
}),
);
// Apply all filters to get combined WHERE clause
const { query, params } = filters.apply();
// query: "position(e.name, {stringFilterXYZ: String}) > 0 AND e.start_time >= {dateTimeFilterABC: DateTime64(3)} AND hasAny({arrayOptionsFilterDEF: Array(String)}, e.tags) = True"