3d584167ad90400886c4b67fea3.../docs/QUERY_BUILDER.md

223 lines
5.4 KiB
Markdown

# TaylorDB Query Builder
The official TypeScript query builder for TaylorDB. It provides a type-safe, fluent, and intuitive API for building and executing queries against your TaylorDB database.
## Features
- **Type-Safe Queries**: Leverage your database schema for full type safety and autocompletion, catching errors at compile-time.
- **Fluent API**: A clean, chainable interface for building complex queries with ease.
- **Full CRUD Support**: Complete implementation for `select`, `insert`, `update`, and `delete` operations.
- **Advanced Filtering**: Filter data with a rich set of operators, nested conditions, and cross-table filters on relations.
- **Complex Selections**: Fetch related data using `with`, select specific columns, or get all columns with `selectAll`.
- **Pagination and Sorting**: Easily paginate and sort your query results.
- **Aggregation Queries**: Perform powerful aggregations with grouping and a variety of aggregate functions.
- **Batch Operations**: Execute multiple queries in a single, efficient request.
- **Real-time Subscriptions**: Subscribe to queries and receive live updates when data changes.
## Installation
```bash
npm install @taylordb/query-builder
```
## Getting Started
### 1. Generate TypeScript Types
First, you need to generate a `taylor.types.ts` file from your TaylorDB schema using the CLI. This file will contain the TypeScript definitions for your database schema, enabling the query builder's type-safety features.
```bash
npx @taylordb/cli generate-schema
```
### 2. Create a Query Builder Instance
Once you have your types file, you can create a new query builder instance.
```typescript
import { createQueryBuilder } from '@taylordb/query-builder';
import { TaylorDatabase } from './taylor.types'; // Import the generated types
const qb = createQueryBuilder<TaylorDatabase>({
baseUrl: 'YOUR_TAYLORDB_BASE_URL',
apiKey: 'YOUR_TAYLORDB_API_KEY',
});
```
## Usage
### Select Queries
#### Basic Select
Select specific columns from a table.
```typescript
const customers = await qb
.selectFrom('customers')
.select(['firstName', 'lastName', 'email'])
.execute();
```
Use `selectAll()` to fetch all columns.
```typescript
const allCustomerData = await qb
.selectFrom('customers')
.selectAll()
.execute();
```
#### Filtering
Use `where` and `orWhere` to filter your results.
```typescript
const johns = await qb
.selectFrom('users')
.select(['name', 'email'])
.where('name', '=', 'John Doe')
.orWhere('email', '=', 'john.doe@example.com')
.execute();
```
You can also nest `where` clauses for complex logic.
```typescript
const users = await qb
.selectFrom('users')
.where(qb =>
qb.where('role', '=', 'admin').orWhere('lastActive', '>', '2023-01-01')
)
.execute();
```
#### Fetching Relations
Include related records from linked tables using `with`.
```typescript
// Get users and all fields from their related posts
const usersWithPosts = await qb
.selectFrom('users')
.select(['id', 'name'])
.with(['posts'])
.execute();
```
You can also provide a function to customize the subquery for the relation.
```typescript
// Get users and only the title of their published posts
const usersWithPublishedPosts = await qb
.selectFrom('users')
.select(['id', 'name'])
.with({
posts: (qb) => qb.select(['title']).where('isPublished', '=', true),
})
.execute();
```
#### Cross-Table Filtering
Filter records based on conditions in a related table.
```typescript
// Get users who have at least one published post
const usersWithPublishedPosts = await qb
.selectFrom('users')
.where('posts', 'hasAnyOf', qb => qb.where('isPublished', '=', true))
.execute();
```
#### Sorting and Pagination
```typescript
const users = await qb
.selectFrom('users')
.select(['id', 'name'])
.orderBy('name', 'asc')
.paginate(2, 25) // Page 2, 25 items per page
.execute();
```
### Insert Queries
Insert single or multiple records. Use `returning` to get data back from the new records.
```typescript
const newUsers = await qb
.insertInto('users')
.values([
{ name: 'John Doe', email: 'john.doe@example.com' },
{ name: 'Jane Doe', email: 'jane.doe@example.com' },
])
.returning(['id', 'name'])
.execute();
```
### Update Queries
Update records matching a `where` clause.
```typescript
const { affectedRecords } = await qb
.update('users')
.set({ name: 'New Name' })
.where('id', '=', 1)
.execute();
```
### Delete Queries
Delete records matching a `where` clause.
```typescript
const { affectedRecords } = await qb
.deleteFrom('users')
.where('id', '=', 1)
.execute();
```
### Aggregation Queries
Perform powerful aggregations on your data.
```typescript
const userStats = await qb
.aggregateFrom('users')
.groupBy('role', 'asc')
.withAggregates({
id: ['count'],
age: ['avg', 'sum'],
})
.execute();
```
### Batch Queries
Execute multiple queries in a single request for improved performance.
```typescript
const [users, newUser] = await qb.batch([
qb.selectFrom('users').select(['id', 'name']),
qb.insertInto('users').values({ name: 'New User' }).returning(['id']),
]).execute();
```
### Real-time Subscriptions
Subscribe to queries and get real-time updates when data changes.
```typescript
const { unsubscribe } = await qb
.selectFrom('users')
.select(['id', 'name'])
.subscribe((users) => {
console.log('Users updated:', users);
});
// To stop listening for updates
unsubscribe();
```