Skip to content

Commit e1fb1e9

Browse files
authored
feat: new query syntax (#185)
1 parent 0ccb185 commit e1fb1e9

File tree

106 files changed

+17198
-14169
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

106 files changed

+17198
-14169
lines changed

docs/overview.md

Lines changed: 60 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ const todoCollection = createCollection({
3333

3434
const Todos = () => {
3535
// Bind data using live queries
36-
const { data: todos } = useLiveQuery((query) =>
37-
query
38-
.from({ todoCollection })
39-
.where('@completed', '=', false)
36+
const { data: todos } = useLiveQuery((q) =>
37+
q
38+
.from({ todo: todoCollection })
39+
.where(({ todo }) => todo.completed)
4040
)
4141

4242
const complete = (todo) => {
@@ -344,22 +344,21 @@ Live queries return collections. This allows you to derive collections from othe
344344
For example:
345345

346346
```ts
347-
import { compileQuery, queryBuilder } from "@tanstack/db"
347+
import { createLiveQueryCollection, eq } from "@tanstack/db"
348348

349-
// Imagine you have a collections of todos.
349+
// Imagine you have a collection of todos.
350350
const todoCollection = createCollection({
351351
// config
352352
})
353353

354354
// You can derive a new collection that's a subset of it.
355-
const query = queryBuilder()
356-
.from({ todoCollection })
357-
.where('@completed', '=', true)
358-
359-
const compiled = compileQuery(query)
360-
compiled.start()
361-
362-
const completedTodoCollection = compiledQuery.results()
355+
const completedTodoCollection = createLiveQueryCollection({
356+
startSync: true,
357+
query: (q) =>
358+
q
359+
.from({ todo: todoCollection })
360+
.where(({ todo }) => todo.completed)
361+
})
363362
```
364363

365364
This also works with joins to derive collections from multiple source collections. And it works recursively -- you can derive collections from other derived collections. Changes propagate efficiently using differential dataflow and it's collections all the way down.
@@ -378,14 +377,18 @@ Use the `useLiveQuery` hook to assign live query results to a state variable in
378377

379378
```ts
380379
import { useLiveQuery } from '@tanstack/react-db'
380+
import { eq } from '@tanstack/db'
381381

382382
const Todos = () => {
383-
const { data: todos } = useLiveQuery(query =>
384-
query
385-
.from({ todoCollection })
386-
.where('@completed', '=', false)
387-
.orderBy({'@created_at': 'asc'})
388-
.select('@id', '@text')
383+
const { data: todos } = useLiveQuery((q) =>
384+
q
385+
.from({ todo: todoCollection })
386+
.where(({ todo }) => eq(todo.completed, false))
387+
.orderBy(({ todo }) => todo.created_at, 'asc')
388+
.select(({ todo }) => ({
389+
id: todo.id,
390+
text: todo.text
391+
}))
389392
)
390393

391394
return <List items={ todos } />
@@ -396,18 +399,23 @@ You can also query across collections with joins:
396399

397400
```ts
398401
import { useLiveQuery } from '@tanstack/react-db'
402+
import { eq } from '@tanstack/db'
399403

400404
const Todos = () => {
401-
const { data: todos } = useLiveQuery(query =>
402-
query
405+
const { data: todos } = useLiveQuery((q) =>
406+
q
403407
.from({ todos: todoCollection })
404-
.join({
405-
type: `inner`,
406-
from: { lists: listCollection },
407-
on: [`@lists.id`, `=`, `@todos.listId`],
408-
})
409-
.where('@lists.active', '=', true)
410-
.select(`@todos.id`, `@todos.title`, `@lists.name`)
408+
.join(
409+
{ lists: listCollection },
410+
({ todos, lists }) => eq(lists.id, todos.listId),
411+
'inner'
412+
)
413+
.where(({ lists }) => eq(lists.active, true))
414+
.select(({ todos, lists }) => ({
415+
id: todos.id,
416+
title: todos.title,
417+
listName: lists.name
418+
}))
411419
)
412420

413421
return <List items={ todos } />
@@ -419,16 +427,16 @@ const Todos = () => {
419427
You can also build queries directly (outside of the component lifecycle) using the underlying `queryBuilder` API:
420428

421429
```ts
422-
import { compileQuery, queryBuilder } from "@tanstack/db"
430+
import { createLiveQueryCollection, eq } from "@tanstack/db"
423431
424-
const query = queryBuilder()
425-
.from({ todoCollection })
426-
.where('@completed', '=', true)
427-
428-
const compiled = compileQuery(query)
429-
compiled.start()
432+
const completedTodos = createLiveQueryCollection({
433+
startSync: true,
434+
query: (q) =>
435+
q.from({ todo: todoCollection })
436+
.where(({ todo }) => eq(todo.completed, true))
437+
})
430438
431-
const results = compiledQuery.results()
439+
const results = completedTodos.toArray
432440
```
433441

434442
Note also that:
@@ -661,16 +669,21 @@ const listCollection = createCollection<TodoList>(queryCollectionOptions({
661669
const Todos = () => {
662670
// Read the data using live queries. Here we show a live
663671
// query that joins across two collections.
664-
const { data: todos } = useLiveQuery((query) =>
665-
query
666-
.from({ t: todoCollection })
667-
.join({
668-
type: 'inner',
669-
from: { l: listCollection },
670-
on: [`@l.id`, `=`, `@t.list_id`]
671-
})
672-
.where('@l.active', '=', true)
673-
.select('@t.id', '@t.text', '@t.status', '@l.name')
672+
const { data: todos } = useLiveQuery((q) =>
673+
q
674+
.from({ todo: todoCollection })
675+
.join(
676+
{ list: listCollection },
677+
({ todo, list }) => eq(list.id, todo.list_id),
678+
'inner'
679+
)
680+
.where(({ list }) => eq(list.active, true))
681+
.select(({ todo, list }) => ({
682+
id: todo.id,
683+
text: todo.text,
684+
status: todo.status,
685+
listName: list.name
686+
}))
674687
)
675688
676689
// ...

examples/react/todo/src/App.tsx

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -271,10 +271,7 @@ const createConfigCollection = (type: CollectionType) => {
271271
const txids = await Promise.all(
272272
transaction.mutations.map(async (mutation) => {
273273
const { original, changes } = mutation
274-
const response = await api.config.update(
275-
original.id as number,
276-
changes
277-
)
274+
const response = await api.config.update(original.id, changes)
278275
return { txid: String(response.txid) }
279276
})
280277
)
@@ -311,10 +308,7 @@ const createConfigCollection = (type: CollectionType) => {
311308
const txids = await Promise.all(
312309
transaction.mutations.map(async (mutation) => {
313310
const { original, changes } = mutation
314-
const response = await api.config.update(
315-
original.id as number,
316-
changes
317-
)
311+
const response = await api.config.update(original.id, changes)
318312
return { txid: String(response.txid) }
319313
})
320314
)
@@ -348,15 +342,12 @@ export default function App() {
348342
// Always call useLiveQuery hooks
349343
const { data: todos } = useLiveQuery((q) =>
350344
q
351-
.from({ todoCollection: todoCollection })
352-
.orderBy(`@created_at`)
353-
.select(`@*`)
345+
.from({ todo: todoCollection })
346+
.orderBy(({ todo }) => todo.created_at, `asc`)
354347
)
355348

356349
const { data: configData } = useLiveQuery((q) =>
357-
q
358-
.from({ configCollection: configCollection })
359-
.select(`@id`, `@key`, `@value`)
350+
q.from({ config: configCollection })
360351
)
361352

362353
// Handle collection type change directly
@@ -381,6 +372,8 @@ export default function App() {
381372

382373
// Define a helper function to update config values
383374
const setConfigValue = (key: string, value: string): void => {
375+
console.log(`setConfigValue`, key, value)
376+
console.log(`configData`, configData)
384377
for (const config of configData) {
385378
if (config.key === key) {
386379
configCollection.update(config.id, (draft) => {
@@ -393,7 +386,7 @@ export default function App() {
393386

394387
// If the config doesn't exist yet, create it
395388
configCollection.insert({
396-
id: Math.random(),
389+
id: Math.round(Math.random() * 1000000),
397390
key,
398391
value,
399392
created_at: new Date(),

0 commit comments

Comments
 (0)