A filter is a Where structure. It is a tree of AND/OR groups whose leaves are field conditions. The query builder turns it into the WHERE clause of the generated SQL.
The Where Structure #
Where is recursive. Each level holds an and or or key with an array of entries. An entry is either a field condition or a nested group:
1
2
3
4
5
6
7
8
9
10
11
import type { Where } from "@lakeql/query-builder"
const filter: Where = {
and: [
{ status: { eq: "shipped" } },
{
or: [{ region: { eq: "eu" } }, { region: { eq: "us" } }],
},
],
}
A field condition maps a column name to a FieldOptions object. Set exactly one operator per field:
1
2
3
4
5
6
{
total: {
gte: "100"
}
}
Field Operators #
FieldOptions supports these operators. Comparison values are passed as strings; is / isNot take a boolean.
| Operator | Meaning |
|---|---|
eq | equals |
neq | not equals |
lt / lte | less than / or equal |
gt / gte | greater than / or equal |
in / notIn | in / not in a set |
like / notLike | SQL LIKE containing the value / negated |
is / isNot | boolean equality with true / false |
On FieldOptions, in and notIn take a single string, not a list.
The query builder also handles startsWith, notStartsWith, endsWith, and notEndsWith as anchored LIKE patterns. These are not on FieldOptions or the GraphQL comparison input types. You reach them only by calling the query builder directly, never through a GraphQL query.
Combining Conditions #
Combine conditions with and / or, and nest them for precedence. A bare filter with several fields and no explicit operator is an implicit AND. The builder normalizes it, splitting each field into its own entry under and before generating SQL.
1
2
3
4
5
6
// Equivalent at runtime (normalizeUserQuery wraps the bare fields in `and`):
const implicit = { status: { eq: "open" }, region: { eq: "eu" } }
const explicit: Where = {
and: [{ status: { eq: "open" } }, { region: { eq: "eu" } }],
}
The bare, multi-field form runs at runtime but does not satisfy the Where type, which only has and/or keys. Annotate it as Field or leave it unannotated.
For the exact normalization rules, see normalizeFilter and normalizeUserQuery in the API reference.