Database

SQL Queries

Querying Managed and Unmanaged schemas using the Fluent API.

SQL-based schemas (Managed and Unmanaged) use a powerful Fluent API that closely mirrors SQL capabilities while providing type safety and ease of use. This API is distinct from the JSON-based API used by Document schemas.

Accessing Schemas

To query a table, you first select the schema using .schema(), then the table using .from().

// Query 'users' table in 'app_data' schema
const users = await nx.db
    .schema('app_data')
    .from('users')
    .select();

// Query 'public' schema (default, can use shortcut if configured)
const publicUsers = await nx.db
    .from('users') // Defaults to public
    .select();

Selection

Selecting columns

You can select specific columns, rename them with aliases, or use JSON paths.

// Select all (default)
.select()

// Select specific columns
.select('id', 'name', 'email')

// Aliasing columns (format: "alias:column")
.select('userId:id', 'fullName:name')

// JSON path selection (for JSONB columns)
.select('meta->settings->theme')

Filtering

The builder supports a wide range of operators. All filters are combined with AND logic by default.

Comparison Operators

MethodSQL EquivalentDescription
.eq('col', val)=Equal to
.neq('col', val)!= or <>Not equal to
.gt('col', val)>Greater than
.gte('col', val)>=Greater than or equal
.lt('col', val)<Less than
.lte('col', val)<=Less than or equal
// Users older than 18
.gt('age', 18)

// Users not in 'archived' status
.neq('status', 'archived')

Pattern Matching

MethodSQL EquivalentDescription
.like('col', '%val%')LIKESimple pattern matching
.ilike('col', '%val%')ILIKECase-insensitive matching
.match('col', 'regex')~Regex match
.imatch('col', 'regex')~*Case-insensitive regex match
// Email ending in @nuvix.io
.like('email', '%@nuvix.io')

// Name starts with 'John' (case-insensitive)
.ilike('name', 'john%')

Lists and Arrays

MethodSQL EquivalentDescription
.in('col', [vals])INValue in list
.notin('col', [vals])NOT INValue not in list
.cs('col', val)@>Contains (Array/JSON)
.cd('col', val)<@Contained by (Array/JSON)
.ov('col', [vals])&&Overlap (Arrays)
// Users with status 'active' or 'pending'
.in('status', ['active', 'pending'])

// Users with 'admin' tag (in string[] column)
.cs('tags', 'admin')

Null Checks

MethodDescription
.null('col')IS NULL
.notnull('col')IS NOT NULL
.is('col', val)IS val (true/false/null)
// Users without a phone number
.null('phone')

Logical Operators

You can group conditions using .or(), .and(), and .not().

// (age > 18 AND status = 'active') OR role = 'admin'
.or((b) => b
    .and((b2) => b2.gt('age', 18).eq('status', 'active'))
    .eq('role', 'admin')
)

Sorting and Pagination

// Sort ascending
.orderAsc('created_at')

// Sort descending
.orderDesc('score')

// Limit and Offset
.limit(10)
.offset(20)

Joins

You can join related tables using the .join() method.

// Join users with their posts
const result = await nx.db
    .schema('app_data')
    .from('users')
    .select('name', 'email')
    .join({ table: 'posts', as: 'user_posts' }, (b) => b
        .select('title', 'created_at')
        .eq('published', true)
    );

Use .fts(), .plfts(), .phfts(), or .wfts() for PostgreSQL full-text search.

// Search description for 'database'
.fts('description', 'database')

// Websearch style (supports "quoted phrases" and -exclusions)
.wfts('description', 'nuvix -"legacy"')

Calling Functions (RPC)

Execute database functions using .fn() or .rpc().

const result = await nx.db
    .schema('app_data')
    .fn('calculate_total')
    .call({ order_id: 123 });

Range Operators

Support for PostgreSQL range types.

MethodOperatorDescription
.sl('col', val)<<Strictly left of
.sr('col', val)>>Strictly right of
.adj('col', val)`--`
.between('col', min, max)BETWEENInclusive range check
// Created between dates
.between('created_at', '2024-01-01', '2024-12-31')

How is this guide?

Last update: