Skip to content

Commit 193062b

Browse files
committed
2 parents 61a0894 + 58a1339 commit 193062b

File tree

29 files changed

+742
-295
lines changed

29 files changed

+742
-295
lines changed

content/docs/ai/coding-assistant.mdx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Without this prompt, Copilot assumes you are using a generic ORM (like TypeORM)
2121
With the System Prompt, it understands the **Context + Repository** pattern:
2222

2323
> **Good AI Output:**
24-
> `await ctx.object('todo').find({ filters: [['priority', '=', 'high']] })`
24+
> `await ctx.object('todo').find({ filters: { priority: 'high' } })`
2525
2626
### 2. Prompting Strategy
2727

@@ -103,10 +103,10 @@ Use the standard generic CRUD API via a context.
103103
const ctx = app.createContext({});
104104
105105
const todos = await ctx.object('todo').find({
106-
filters: [
107-
['completed', '=', false],
108-
['priority', '=', 'high']
109-
],
106+
filters: {
107+
completed: false,
108+
priority: 'high'
109+
},
110110
fields: ['title', 'owner.name'], // Select specific fields & relations
111111
sort: [['created_at', 'desc']],
112112
skip: 0,

content/docs/data-access/best-practices.mdx

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,10 @@ The **JSON-DSL** is ObjectQL's core query language - a structured JSON represent
4040
```typescript
4141
const tasks = await app.object('task').find({
4242
fields: ['name', 'status', 'due_date'],
43-
filters: [
44-
['status', '=', 'active'],
45-
'and',
46-
['priority', '>=', 3]
47-
],
43+
filters: {
44+
status: 'active',
45+
priority: { $gte: 3 }
46+
},
4847
sort: [['due_date', 'asc']],
4948
skip: 0,
5049
limit: 20
@@ -59,7 +58,7 @@ const tasks = await app.object('task').find({
5958
```typescript
6059
// Returns ALL fields (inefficient)
6160
await app.object('user').find({
62-
filters: [['status', '=', 'active']]
61+
filters: { status: 'active' }
6362
});
6463
```
6564

@@ -68,7 +67,7 @@ await app.object('user').find({
6867
// Returns only needed fields (efficient)
6968
await app.object('user').find({
7069
fields: ['id', 'name', 'email'],
71-
filters: [['status', '=', 'active']]
70+
filters: { status: 'active' }
7271
});
7372
```
7473

@@ -79,17 +78,16 @@ await app.object('user').find({
7978
**Bad:**
8079
```typescript
8180
// Filters on non-indexed field
82-
filters: [['description', 'contains', 'urgent']]
81+
filters: { description: { $contains: 'urgent' } }
8382
```
8483

8584
**Good:**
8685
```typescript
8786
// Filters on indexed field first, then post-filter if needed
88-
filters: [
89-
['status', '=', 'open'], // Indexed
90-
'and',
91-
['priority', '=', 'high'] // Indexed
92-
]
87+
filters: {
88+
status: 'open', // Indexed
89+
priority: 'high' // Indexed
90+
}
9391
```
9492

9593
**Impact:** Can improve query speed by 10-100x depending on dataset size.
@@ -100,15 +98,15 @@ filters: [
10098
```typescript
10199
// Returns all records (dangerous)
102100
await app.object('order').find({
103-
filters: [['year', '=', 2024]]
101+
filters: { year: 2024 }
104102
});
105103
```
106104

107105
**Good:**
108106
```typescript
109107
// Paginated results (safe and fast)
110108
await app.object('order').find({
111-
filters: [['year', '=', 2024]],
109+
filters: { year: 2024 },
112110
limit: 50,
113111
skip: page * 50,
114112
sort: [['created_at', 'desc']]
@@ -431,7 +429,7 @@ const tasksWithAssignee = await Promise.all(
431429
const tasks = await taskRepo.find();
432430
const userIds = tasks.map(t => t.assignee_id);
433431
const users = await userRepo.find({
434-
filters: [['id', 'in', userIds]]
432+
filters: { id: { $in: userIds } }
435433
});
436434
const userMap = new Map(users.map(u => [u.id, u]));
437435
const tasksWithAssigneeBatched = tasks.map((task) => ({
@@ -516,7 +514,7 @@ query Dashboard {
516514
// Hook: Automatically assign to least-busy team member
517515
async function autoAssign(task: any) {
518516
const members = await app.object('user').aggregate({
519-
filters: [['team_id', '=', task.team_id]],
517+
filters: { team_id: task.team_id },
520518
groupBy: ['id', 'name'],
521519
aggregate: [
522520
{ func: 'count', field: 'tasks.id', alias: 'task_count' }
@@ -581,7 +579,7 @@ AND priority = 'high' AND invalid_function(status);
581579
**Bad (Application-level aggregation):**
582580
```typescript
583581
const orders = await app.object('order').find({
584-
filters: [['status', '=', 'paid']]
582+
filters: { status: 'paid' }
585583
});
586584

587585
// Slow: Iterating in application code
@@ -594,7 +592,7 @@ for (const order of orders) {
594592
**Good (Database-level aggregation):**
595593
```typescript
596594
const stats = await app.object('order').aggregate({
597-
filters: [['status', '=', 'paid']],
595+
filters: { status: 'paid' },
598596
groupBy: ['customer_id'],
599597
aggregate: [
600598
{ func: 'sum', field: 'amount', alias: 'total_revenue' },
@@ -620,7 +618,7 @@ const uniqueCustomers = [...new Set(orders.map(o => o.customer_id))];
620618
**Good:**
621619
```typescript
622620
const uniqueCustomers = await app.object('order').distinct('customer_id', {
623-
filters: [['year', '=', 2024]]
621+
filters: { year: 2024 }
624622
});
625623
```
626624

@@ -661,18 +659,19 @@ indexes:
661659
662660
**Bad (OR requires multiple index scans):**
663661
```typescript
664-
filters: [
665-
['status', '=', 'pending'],
666-
'or',
667-
['status', '=', 'active']
668-
]
662+
filters: {
663+
$or: [
664+
{ status: 'pending' },
665+
{ status: 'active' }
666+
]
667+
}
669668
```
670669

671670
**Good (IN uses single index scan):**
672671
```typescript
673-
filters: [
674-
['status', 'in', ['pending', 'active']]
675-
]
672+
filters: {
673+
status: { $in: ['pending', 'active'] }
674+
}
676675
```
677676

678677
**Impact:** 2-5x faster for large tables.
@@ -693,7 +692,7 @@ await app.object('order').find({
693692
**Good (Cursor pagination using last ID):**
694693
```typescript
695694
await app.object('order').find({
696-
filters: [['id', '>', lastSeenId]],
695+
filters: { id: { $gt: lastSeenId } },
697696
limit: 50,
698697
sort: [['id', 'asc']]
699698
});
@@ -754,7 +753,7 @@ GET /api/data/tasks?status=active&limit=20
754753
**After:**
755754
```typescript
756755
await app.object('task').find({
757-
filters: [['status', '=', 'active']],
756+
filters: { status: 'active' },
758757
limit: 20
759758
});
760759
```
@@ -764,7 +763,7 @@ await app.object('task').find({
764763
**Before:**
765764
```typescript
766765
const tasks = await app.object('task').find({
767-
filters: [['status', '=', 'active']],
766+
filters: { status: 'active' },
768767
expand: {
769768
assignee: { fields: ['name', 'email'] }
770769
}

content/docs/data-access/index.mdx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,10 @@ const ctx = app.createContext({ isSystem: true });
6161
// Query data with filters
6262
const products = await ctx.object('product').find({
6363
fields: ['name', 'price', 'category'],
64-
filters: [
65-
['category', '=', 'electronics'],
66-
'and',
67-
['price', '<', 1000]
68-
],
64+
filters: {
65+
category: 'electronics',
66+
price: { $lt: 1000 }
67+
},
6968
sort: [['price', 'asc']],
7069
top: 10
7170
});

content/docs/data-access/querying.mdx

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ The `find` method recovers a list of records matching specific criteria.
1515

1616
```typescript
1717
const products = await app.object('product').find({
18-
filters: [
19-
['category', '=', 'electronics'],
20-
['price', '>', 500]
21-
],
18+
filters: {
19+
category: 'electronics',
20+
price: { $gt: 500 }
21+
},
2222
fields: ['name', 'price', 'category'],
2323
sort: ['-price'], // Descending
2424
skip: 0,
@@ -28,19 +28,26 @@ const products = await app.object('product').find({
2828

2929
### Filters
3030

31-
Filters are defined as a 2D array: `[[ field, operator, value ]]`.
31+
Filters use an object-based syntax with implicit equality and operator objects.
3232

3333
**Implicit AND**:
3434
```typescript
35-
filters: [
36-
['status', '=', 'active'],
37-
['stock', '>', 0]
38-
]
35+
filters: {
36+
status: 'active',
37+
stock: { $gt: 0 }
38+
}
3939
// SQL: WHERE status = 'active' AND stock > 0
4040
```
4141

4242
**Explicit OR**:
43-
Use the `_or` special operator in complex filters (see advanced docs).
43+
```typescript
44+
filters: {
45+
$or: [
46+
{ status: 'active' },
47+
{ featured: true }
48+
]
49+
}
50+
```
4451

4552
### Sorting
4653

@@ -66,13 +73,13 @@ Updates are always bulk operations targeted by `filters`. To update a single rec
6673
```typescript
6774
// Update specific record
6875
await app.object('user').update(
69-
{ filters: [['_id', '=', '123']] }, // Target
76+
{ filters: { _id: '123' } }, // Target
7077
{ doc: { status: 'active' } } // Change
7178
);
7279

7380
// Bulk update
7481
await app.object('product').update(
75-
{ filters: [['stock', '=', 0]] },
82+
{ filters: { stock: 0 } },
7683
{ doc: { status: 'out_of_stock' } }
7784
);
7885
```
@@ -82,7 +89,7 @@ await app.object('product').update(
8289
```typescript
8390
// Delete specific record
8491
await app.object('user').delete({
85-
filters: [['_id', '=', '123']]
92+
filters: { _id: '123' }
8693
});
8794
```
8895

@@ -141,9 +148,9 @@ There are two ways to filter based on relationships:
141148
Find tasks where the *project's status* is active.
142149
*(Note: Requires a driver that supports SQL Joins)*
143150
```typescript
144-
filters: [
145-
['project.status', '=', 'active']
146-
]
151+
filters: {
152+
'project.status': 'active'
153+
}
147154
```
148155

149156
**B. Filter the Expanded List**
@@ -152,7 +159,7 @@ Find projects, but only include *completed* tasks in the expansion.
152159
app.object('project').find({
153160
expand: {
154161
tasks: {
155-
filters: [['status', '=', 'completed']]
162+
filters: { status: 'completed' }
156163
}
157164
}
158165
})
@@ -165,7 +172,7 @@ ObjectQL supports SQL-like aggregation via the `aggregate()` method on the repos
165172
```typescript
166173
const stats = await app.object('order').aggregate({
167174
// 1. Filter first
168-
filters: [['status', '=', 'paid']],
175+
filters: { status: 'paid' },
169176

170177
// 2. Group by specific fields
171178
groupBy: ['customer_id'],

0 commit comments

Comments
 (0)