Gemini Backend: LowCode REST API - parte 3

5 minuti di lettura

Gemini Rest - part 3

Nel primo articolo e nel secondo articolo delle serie Gemini Backend: LowCode REST API abbiamo visto come è semplice creare delle API REST CRUD partendo da un modello dati tipizzato e come sfruttare le feature di Gemini per filtrare e/o contare i dati delle varie entità REST.

Gli esempi sono molto semplici ovviamente e lo step successivo è proprio quello di capire come trattare entità che hanno un numero elevato di elementi, anche se filtrati. Le tecniche possono essere diverse, e molto dipende dalle feature che il driver sottostante di persistenza di mette a disposizione (in questo caso MongoDB).

Gemini supporta la paginazione mediante la tecnica dello start e limit. Tutte le API di recupero dati possono contenere questi due campi per limitare il numero dei dati letti dall'entità sottostante e per procedere quindi per pagine successive. La tecnica è molto semplice e di solito viene usata in congiunzione con ordinamenti e filtri per scorrere lungo i dati a disposizione in modo ordinato e puntuale, ma lo vedremo nelle sezioni successive.

Prima di iniziare: due parole su Gemini

Gemini è un framework che sto sviluppando per velocizzare la parte di sviluppo/utilizzo di API REST che mi capita di dover scrivere nel mio lavoro.

Il realtà è composto da una serie di moduli che backend e frontend che consentono di creare in poco tempo applicazioni web complete (fullstack) di stile gestionale, senza togliere al programmatore la possibilità di customizzare ed inserire il proprio codice sia lato backend che frontend.

In questo articolo ci concentriamo sulla parte backend, con il generatore di API REST, ma potete trovare tutti i dettagli ed i casi d'uso principali del progetto sul repository github ufficiale.

Iniziamo - Step 0 - Run di Gemini

Negli articoli precedenti (parte 1 parte2) viene spiegato in modo più approfondito come avviare l'immagine Docker del backend. Dateci un occhiata se vi è sfuggito, soprattutto per quanto riguarda la parte di definizione dello schema delle entità REST che contiene categorie e prodotti.

L'immagine è pubblica, non avete bisogno di installare nulla (a parte Docker se non lo avete).

docker run -p 8080:8080 \
-e GEMINI_SCHEMAS=/schemas/product_schema.yaml \
-e GEMINI_MONGODB_URL="mongodb+srv://_mongo_user:_mongo_pwd_@__path__.mongodb.net/db?retryWrites=true&w=majority" \
-e GEMINI_MONGODB_DB=starter \
-v $(pwd)/product_schema.yaml:/schemas/product_schema.yaml:ro \
aat7/gemini-micronaut-mongodb-restapi

Ora Gemini sarà in ascolto sulla porta 8080.

Step 1 - Inserimento dati

Per un test esaustivo con le API di paginazione ha senso inserire un numero di record consistente. Sempre nel repository dove c'è lo schema di esempio (qui) potete trovare un semplice script in node per inserire un pò di prodotti random.

Potete cambiare lo script a piacimento, di default vengono inseriti 50 record alla volta per 10 chiamate REST diverse, in totale 500 record sull'entità prodotti.

# From the root of the Gemini Repo
cd starters/examples/product-sample

# Install required dependencies (Axios)
npm install

# Run the script
node insertRandomProduct.js

Step 2 - API & Paginazione

Veniamo ora alla parte principale, ovvero usare i parametri start e limit nelle chiamate di recupero dati

Count prodotti inseriti

Prima di tutto vediamo quanti record abbiamo a disposizione. Sappiamo che con una GET a /entity/{entityName}/recordCounts è possibile contare tutti i record di un entità.

curl "http://localhost:8080/entity/product/recordCounts"
{
    "status": "success",
    "data": {
        "count": 560
    },
    "meta": {
        "elapsedTime": "46ms"
    }
}

I record sono 560, quelli appena inseriti dallo script, più quelli che abbiamo inserito negli articoli precedenti.

Start e Limit

Ci siamo, proviamo a fare qualche richiesta paginata dell'entità Products.

# First 10 elements
curl "http://localhost:8080/data/product?limit=10&start=0"

# Following 10 elements
curl "http://localhost:8080/data/product?limit=10&start=10"

L'API è semplicissima, limit serve per impostare la grandezza della pagina, mentre start per spostarsi in avanti.

Con Order By

L'API è più utile se combinata con l'ordinamento usando orderBy sia crescente che decrescente.

# First 20 elements ordered by Name (ascending)
curl "http://localhost:8080/data/product?limit=20&orderBy=name&start=0"

# Following 20 elements ordered by Name (descending)
curl "http://localhost:8080/data/product?limit=20&orderBy=-name&start=0"

Con filtri

Ovviamente è possibile anche usare filtri insieme a paginazione ed ordinamento.

# First 5 elements ordered by Name (ascending) where name contains Random
curl "http://localhost:8080/data/product?limit=5&orderBy=name&start=0&name[contains]=Random"

Come gestire milioni di record?

Quello che abbiamo visto finora in realtà non basta a gestire entità che hanno milioni di record. Se eseguite infatti una GET alla root dell'entità prodotti Gemini proverà a leggere tutti i dati dell'entità.

# We have the resulting array of more than 500 elements
curl "http://localhost:8080/data/product"

Permettere questo comportamento non è una buona soluzione con entità molto corpose. Per questo Gemini accetta tra le sue configurazioni anche la strategia REST a cui ogni entità dovrebbe essere esposta, evitando quindi delle GET troppo pesanti e favorendo la paginazione. Ma questo aspetto lo vedremo in un altro articolo.

Conclusioni

In questo articolo abbiamo fatto un'altro passo avanti nell'esplorazione delle feature del modulo backend di Gemini. Abbiamo visto in particolare come usare start, limit ed orderBy per la paginazione delle entità REST, e come è possibile usarli anche in congiunzione con i filtri.

Tenete in considerazione che Gemini è si in fase di sviluppo, ma è anche attualmente in produzione in aziende con cui collaboro. Se siete curiosi e volete provare a vedere se Gemini può essere utile per il vostro caso d'uso concreto contattatemi pure, sarò felice di aiutare e magari estendere la piattaforma.