Con Astro DB è possibile eseguire una query sul database da qualsiasi pagina o endpoint del progetto utilizzando l'ORM e il query builder. Prima di eseguire una qualunque query in Astro DB, è necessario importare l'oggetto db
da astro:db
:
import { db } from 'astro:db';
Una volta importato l'ORM, possiamo utilizzare i metodi di Drizzle per eseguire ogni tipo di operazione sui dati. Drizzle supporta quasi tutte le funzioni e le capacità di query di ogni dialetto. Nel caso fosse necessario eseguire query SQL personalizzate o particolarmente complesse, Drizzle fornisce l'operatore sql
.
Qui ci concentreremo sulle funzionalità di utilizzo più ricorrente, lasciando al lettore lo studio dei casi d'uso più avanzati nella documentazione online.
Select
Il metodo db.select()
permette di creare una query SELECT
sul database. Nell'esempio che segue, selezioniamo tutte le righe della tabella Columns
, includendo tutte le colonne:
const categories = await db
.select()
.from(Categories);
Possiamo selezionare colonne specifiche passando a select()
un oggetto contenente i campi richiesti:
const categories = await db.select({
id: Categories.id,
name: Categories.name,
}).from(Categories);
Per filtrare i risultati della query, abbiamo a disposizione numerosi operatori come eq
(equal), lt
(less than), gt
(greater than), ne
(not equal), che utilizzeremo all'interno del metodo where()
, come nell'esempio che segue:
const result = await db
.select()
.from(Categories)
.where(eq(Categories.id, lastRecord[0].catId));
Il risultato conterrà tutti i record della tabella Categories
in cui l'id della categoria è uguale (eq
) al valore lastRecord[0].catId
.
Relazioni tra tabelle
Come anticipato nella lezione precedente, in Astro DB è possibile prelevare contemporaneamente dati da più tabelle utilizzando una join SQL. Per creare una join, è necessario estendere l'istruzione db.select()
con un operatore di join, specificando la tabella da unire e una condizione per abbinare le righe tra le due tabelle.
Nell'esempio che segue, eseguiamo una inner join tra le tabelle Categories
e Todos
. La funzione innerJoin()
unisce le categorie della tabella Categories
con i task corrispondenti presenti nella tabella Todos
in base al valore del campo Categories.id
.
const todos = await db
.select()
.from(Todos)
.innerJoin(Categories, eq(Todos.catId, Categories.id));
Insert
La documentazione di Astro DB avverte che
Per accettare l'input dell'utente, come la gestione delle richieste di moduli e l'inserimento di dati nel database remoto, è necessario configurare il progetto Astro per il rendering on-demand e aggiungere un adattatore SSR per l'ambiente di distribuzione.
Una volta configurato Astro per il rendering on-demand, possiamo inserire il nostro primo record. Nell'esempio che segue, viene creato un nuovo record nella tabella Todos
con i valori delle tre variabili task
, catId
e done
:
const result = await db
.insert(Todos)
.values({ task, catId, done })
.returning();
Si noterà l'utilizzo del metodo returning()
. Questo restituisce un oggetto con i campi dell'ultimo record inserito. Nell'esempio qui sopra, returning()
restituisce tutti i campi ma è anche possibile passare un oggetto i cui elementi specifichino i campi della risposta.
const result = await db
.insert(Todos)
.values({ task, catId, done })
.returning({ insertedId: Todos.id });
Update
Oltre ad inserire nuovi record, è ovviamente possibile modificare record esistenti. A questo scopo Drizzle fornisce il metodo update().set()
. Ecco un esempio:
await db.update(Todos)
.set({ task: 'Learn how to use Astro DB' }).
where(eq(Todos.id, 5));
Per invertire un valore boolean, possiamo utilizzare l'operatore not()
. Se dovessimo cambiare lo stato di un task da completare a completato, potremmo utilizzare il seguente codice:
const updatedRecord = await db.update(Todos)
.set({ done: not(Todos.done) })
.where(eq(Todos.id, itemId))
.returning();
Come in precedenza, .returning()
restituisce tutti i campi del record modificato.
Delete
Infine, il metodo delete()
permette di eliminare specifici record in base ai parametri della richiesta. Nell'esempio che segue, eliminiamo un record in base all'id:
await db
.delete(Todos)
.where(eq(Todos.id, itemId));
Un'applicazione con Astro DB e htmx
Completata l'introduzione ad htmx e Astro DB, nelle prossime lezioni proveremo a mettere insieme quello che abbiamo imparato e creeremo un'applicazione interattiva che ci permetta di gestire una semplice todo list.
- creeremo due tabelle:
Todos
eCategories
. Ad ogni riga della tabellaTodos
dovrà essere assegnata una categoria. - Creeremo un form per l'inserimento di righe (task) nella tabella
Todos
utilizzando gli attributi di htmx. - All'invio del modulo, sarà creato un nuovo record nella tabella
Todos
e contemporaneamente sulla pagina sarà visualizzata una card con i dati del task. - Il task potrà essere contrassegnato come completo o da completare e potrà essere eliminato del tutto.
Quella che segue è un'anteprima dell'interfaccia dell'applicazione.