Creare un'applicazione bancaria online con Spanner

1. Panoramica

Spanner è un servizio di database completamente gestito, scalabile orizzontalmente e distribuito a livello globale, ideale per carichi di lavoro operativi relazionali e non relazionali. Oltre alle funzionalità di base, Spanner offre potenti funzionalità avanzate che consentono di creare applicazioni intelligenti e basate sui dati.

Questo codelab si basa sulla comprensione di base di Spanner e approfondisce l'utilizzo delle sue integrazioni avanzate per migliorare le funzionalità di analisi ed elaborazione dei dati, utilizzando come base un'applicazione di online banking.

Ci concentreremo su tre funzionalità avanzate chiave:

  • Integrazione di Vertex AI: scopri come integrare perfettamente Spanner con Vertex AI, la piattaforma di AI di Google Cloud. Scoprirai come richiamare i modelli Vertex AI direttamente dalle query SQL di Spanner, consentendo trasformazioni e previsioni potenti nel database, in modo che la nostra applicazione bancaria possa classificare automaticamente le transazioni per casi d'uso come il monitoraggio del budget e il rilevamento delle anomalie.
  • Ricerca a testo intero: scopri come implementare la funzionalità di ricerca a testo intero in Spanner. Esplorerai l'indicizzazione dei dati di testo e la scrittura di query efficienti per eseguire ricerche basate su parole chiave nei tuoi dati operativi, consentendo una potente scoperta dei dati, ad esempio la ricerca efficiente dei clienti per indirizzo email all'interno del nostro sistema bancario.
  • Query federate di BigQuery: scopri come sfruttare le funzionalità di query federate di Spanner per eseguire query direttamente sui dati che si trovano in BigQuery. Ciò ti consente di combinare i dati operativi in tempo reale di Spanner con i set di dati analitici di BigQuery per ottenere approfondimenti e report completi senza duplicazione dei dati o processi ETL complessi, supportando vari casi d'uso nella nostra applicazione bancaria, come campagne di marketing mirate, combinando i dati dei clienti in tempo reale con tendenze storiche più ampie di BigQuery.

Obiettivi didattici

  • Come configurare un'istanza di Spanner.
  • Come creare un database e delle tabelle.
  • Come caricare i dati nelle tabelle del database Spanner.
  • Come chiamare i modelli Vertex AI da Spanner.
  • Come eseguire query sul database Spanner utilizzando la ricerca approssimativa e la ricerca a testo intero.
  • Come eseguire query federate su Spanner da BigQuery.
  • Come eliminare l'istanza Spanner.

Che cosa ti serve

  • Un progetto cloud Google Cloud collegato a un account di fatturazione.
  • Un browser web, ad esempio Chrome o Firefox.

2. Configurazione e requisiti

Crea un progetto

Se hai già un progetto cloud Google Cloud con la fatturazione abilitata, fai clic sul menu a discesa di selezione del progetto in alto a sinistra nella console:

Progetto esistente

Con un progetto selezionato, vai ad Abilitare le API richieste.

Se non hai ancora un Account Google (Gmail o Google Apps), devi crearne uno. Accedi alla console di Google Cloud Platform (console.cloud.google.com) e crea un nuovo progetto.

Fai clic sul pulsante "NUOVO PROGETTO" nella finestra di dialogo risultante per creare un nuovo progetto:

Nuovo progetto

Se non hai ancora un progetto, dovresti visualizzare una finestra di dialogo come questa per creare il primo:

Finestra di dialogo Progetto

La finestra di dialogo successiva per la creazione del progetto ti consente di inserire i dettagli del nuovo progetto.

Ricorda l'ID progetto, che è un nome univoco tra tutti i progetti Google Cloud. In questo codelab verrà chiamato PROJECT_ID.

Dettagli del progetto

Successivamente, se non l'hai ancora fatto, devi attivare la fatturazione nella console per gli sviluppatori per utilizzare le risorse Google Cloud e attivare l'API Spanner, l'API Vertex AI, l'API BigQuery e l'API BigQuery Connection.

Fatturazione del progetto

I prezzi di Spanner sono documentati qui. Gli altri costi associati ad altre risorse verranno documentati nelle pagine dei prezzi specifiche.

I nuovi utenti di Google Cloud Platform possono beneficiare di una prova senza costi di 300$.

Configurazione di Google Cloud Shell

In questo codelab utilizzeremo Google Cloud Shell, un ambiente a riga di comando in esecuzione nel cloud.

Questa macchina virtuale basata su Debian viene caricata con tutti gli strumenti di sviluppo di cui avrai bisogno. Offre una home directory permanente da 5 GB e viene eseguita in Google Cloud, migliorando notevolmente le prestazioni e l'autenticazione della rete. Ciò significa che per questo codelab ti servirà solo un browser.

Per attivare Cloud Shell dalla console Cloud, fai clic su Attiva Cloud Shell Icona di Cloud Shell (bastano pochi istanti per eseguire il provisioning e connettersi all'ambiente).

Cloud Shell

Una volta eseguita la connessione a Cloud Shell, dovresti vedere che il tuo account è già autenticato e il progetto è già impostato sul tuo PROJECT_ID.

gcloud auth list

Output previsto:

Credentialed Accounts

ACTIVE: *
ACCOUNT: <myaccount>@<mydomain>.com
gcloud config list project

Output previsto:

[core]
project = <PROJECT_ID>

Se per qualche motivo il progetto non è impostato, esegui questo comando:

gcloud config set project <PROJECT_ID>

Stai cercando il tuo PROJECT_ID? Controlla l'ID che hai utilizzato nei passaggi di configurazione o cercalo nella dashboard di Cloud Console:

ID progetto

Cloud Shell imposta anche alcune variabili di ambiente per impostazione predefinita, che potrebbero essere utili quando esegui i comandi futuri.

echo $GOOGLE_CLOUD_PROJECT

Output previsto:

<PROJECT_ID>

Abilita le API richieste

Abilita le API Spanner, Vertex AI e BigQuery per il tuo progetto:

gcloud services enable spanner.googleapis.com
gcloud services enable aiplatform.googleapis.com
gcloud services enable bigquery.googleapis.com
gcloud services enable bigqueryconnection.googleapis.com

Riepilogo

In questo passaggio, hai configurato il progetto se non ne avevi già uno, hai attivato Cloud Shell e hai abilitato le API richieste.

Prossimo

Il passaggio successivo consiste nel configurare l'istanza Spanner.

3. Configura un'istanza di Spanner

Crea l'istanza Spanner

In questo passaggio configurerai un'istanza Spanner per il codelab. Per farlo, apri Cloud Shell ed esegui questo comando:

export SPANNER_INSTANCE=cloudspanner-onlinebanking
gcloud spanner instances create $SPANNER_INSTANCE \
  --config=regional-us-central1 \
  --description="Spanner Online Banking" \
  --nodes=1 \
  --edition=ENTERPRISE \
  --default-backup-schedule-type=NONE

Output previsto:

Creating instance...done.

Riepilogo

In questo passaggio hai creato l'istanza Spanner.

Prossimo

A questo punto, preparerai l'applicazione iniziale e creerai il database e lo schema.

4. Crea un database e uno schema

Prepara la richiesta iniziale

In questo passaggio creerai il database e lo schema tramite il codice.

Innanzitutto, crea un'applicazione Java denominata onlinebanking utilizzando Maven:

mvn -B archetype:generate \
  -DarchetypeGroupId=org.apache.maven.archetypes \
  -DgroupId=com.google.codelabs \
  -DartifactId=onlinebanking \
  -DjavaCompilerVersion=1.8 \
  -DjunitVersion=4.13.2 \
  -DarchetypeVersion=1.5

Estrai e copia i file di dati che aggiungeremo al database (vedi qui per il repository di codice):

git clone https://github.com/GoogleCloudPlatform/cloud-spanner-samples.git
cp -r ./cloud-spanner-samples/banking/data ./onlinebanking

Vai alla cartella dell'applicazione:

cd onlinebanking

Apri il file Maven pom.xml. Aggiungi la sezione di gestione delle dipendenze per utilizzare la distinta materiali Maven per gestire la versione delle librerie Google Cloud:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>libraries-bom</artifactId>
      <version>26.56.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

Ecco l'aspetto dell'editor e del file: cloud shell

Assicurati che la sezione dependencies includa le librerie che l'applicazione utilizzerà:

<dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-nop</artifactId>
    <version>2.0.9</version>
  </dependency>
  <dependency>
    <groupId>com.opencsv</groupId>
    <artifactId>opencsv</artifactId>
    <version>5.10</version>
  </dependency>
  <dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-spanner</artifactId>
  </dependency>
  <dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-bigquery</artifactId>
  </dependency>
  <dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-bigqueryconnection</artifactId>
  </dependency>
</dependencies>

Infine, sostituisci i plug-in di build in modo che l'applicazione venga pacchettizzata in un file JAR eseguibile:

<build>
  <plugins>
    <plugin>
      <artifactId>maven-resources-plugin</artifactId>
      <version>3.3.1</version>
      <executions>
        <execution>
          <id>copy-resources</id>
          <phase>process-resources</phase>
          <goals>
            <goal>copy-resources</goal>
          </goals>
          <configuration>
            <outputDirectory>${project.build.directory}/${project.artifactId}-resources</outputDirectory>
            <resources>
              <resource>
                <directory>resources</directory>
                <filtering>true</filtering>
              </resource>
            </resources>
          </configuration>
        </execution>
      </executions>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-dependency-plugin</artifactId>
      <version>3.8.1</version>
      <executions>
        <execution>
          <id>copy-dependencies</id>
          <phase>prepare-package</phase>
          <goals>
            <goal>copy-dependencies</goal>
          </goals>
          <configuration>
            <outputDirectory>${project.build.directory}/${project.artifactId}-resources/lib</outputDirectory>
            <overWriteReleases>false</overWriteReleases>
            <overWriteSnapshots>false</overWriteSnapshots>
            <overWriteIfNewer>true</overWriteIfNewer>
          </configuration>
        </execution>
      </executions>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-jar-plugin</artifactId>
      <version>3.4.2</version>
      <configuration>
        <finalName>${project.artifactId}</finalName>
        <outputDirectory>${project.build.directory}</outputDirectory>
        <archive>
          <index>false</index>
          <manifest>
            <mainClass>com.google.codelabs.App</mainClass>
            <addClasspath>true</addClasspath>
            <classpathPrefix>${project.artifactId}-resources/lib/</classpathPrefix>
          </manifest>
        </archive>
      </configuration>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-failsafe-plugin</artifactId>
      <version>3.2.5</version>
      <executions>
        <execution>
          <goals>
            <goal>integration-test</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-surefire-plugin</artifactId>
      <version>3.2.5</version>
      <configuration>
        <useSystemClassLoader>false</useSystemClassLoader>
      </configuration>
    </plugin>
  </plugins>
</build>

Salva le modifiche apportate al file pom.xml selezionando "Salva" nel menu "File " dell'editor di Cloud Shell o premendo Ctrl+S.

Ora che le dipendenze sono pronte, aggiungerai codice all'app per creare uno schema, alcuni indici (inclusa la ricerca) e un modello di AI connesso a un endpoint remoto. In questo codelab, creerai questi artefatti e aggiungerai altri metodi a questa classe.

Apri App.java in onlinebanking/src/main/java/com/google/codelabs e sostituisci i contenuti con il seguente codice:

package com.google.codelabs;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;

import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.spanner.Database;
import com.google.cloud.spanner.DatabaseAdminClient;
import com.google.cloud.spanner.DatabaseClient;
import com.google.cloud.spanner.DatabaseId;
import com.google.cloud.spanner.Spanner;
import com.google.cloud.spanner.SpannerException;
import com.google.cloud.spanner.SpannerExceptionFactory;
import com.google.cloud.spanner.SpannerOptions;
import com.google.spanner.admin.database.v1.CreateDatabaseMetadata;

public class App {

  // Create the Spanner database and schema
  public static void create(DatabaseAdminClient dbAdminClient, DatabaseId db,
      String location, String model) {
    System.out.println("Creating Spanner database...");
    List<String> statements = Arrays.asList(
      "CREATE TABLE Customers (\n"
          + "  CustomerId INT64 NOT NULL,\n"
          + "  FirstName STRING(256) NOT NULL,\n"
          + "  LastName STRING(256) NOT NULL,\n"
          + "  FullName STRING(512) AS (FirstName || ' ' || LastName) STORED,\n"
          + "  Email STRING(512) NOT NULL,\n"
          + "  EmailTokens TOKENLIST AS\n"
          + "    (TOKENIZE_SUBSTRING(Email, ngram_size_min=>2, ngram_size_max=>3,\n"
          + "      relative_search_types=>[\"all\"])) HIDDEN,\n"
          + "  Address STRING(MAX)\n"
          + ") PRIMARY KEY (CustomerId)",

      "CREATE INDEX CustomersByEmail\n"
          + "ON Customers(Email)",

      "CREATE SEARCH INDEX CustomersFuzzyEmail\n"
          + "ON Customers(EmailTokens)",

      "CREATE TABLE Accounts (\n"
          + "  AccountId INT64 NOT NULL,\n"
          + "  CustomerId INT64 NOT NULL,\n"
          + "  AccountType STRING(256) NOT NULL,\n"
          + "  Balance NUMERIC NOT NULL,\n"
          + "  OpenDate TIMESTAMP NOT NULL\n"
          + ") PRIMARY KEY (AccountId)",

      "CREATE INDEX AccountsByCustomer\n"
          + "ON Accounts (CustomerId)",

      "CREATE TABLE TransactionLedger (\n"
          + "  TransactionId INT64 NOT NULL,\n"
          + "  AccountId INT64 NOT NULL,\n"
          + "  TransactionType STRING(256) NOT NULL,\n"
          + "  Amount NUMERIC NOT NULL,\n"
          + "  Timestamp TIMESTAMP NOT NULL"
          + "  OPTIONS(allow_commit_timestamp=true),\n"
          + "  Category STRING(256),\n"
          + "  Description STRING(MAX),\n"
          + "  CategoryTokens TOKENLIST AS (TOKENIZE_FULLTEXT(Category)) HIDDEN,\n"
          + "  DescriptionTokens TOKENLIST AS (TOKENIZE_FULLTEXT(Description)) HIDDEN\n"
          + ") PRIMARY KEY (AccountId, TransactionId),\n"
          + "INTERLEAVE IN PARENT Accounts ON DELETE CASCADE",

      "CREATE INDEX TransactionLedgerByAccountType\n"
          + "ON TransactionLedger(AccountId, TransactionType)",

      "CREATE INDEX TransactionLedgerByCategory\n"
          + "ON TransactionLedger(AccountId, Category)",

      "CREATE SEARCH INDEX TransactionLedgerTextSearch\n"
          + "ON TransactionLedger(CategoryTokens, DescriptionTokens)",

      "CREATE MODEL TransactionCategoryModel\n"
          + "INPUT (prompt STRING(MAX))\n"
          + "OUTPUT (content STRING(MAX))\n"
          + "REMOTE OPTIONS (\n"
          + "  endpoint = '//aiplatform.googleapis.com/projects/" + db.getInstanceId().getProject()
              + "/locations/" + location + "/publishers/google/models/" + model + "',\n"
          + "  default_batch_size = 1\n"
          + ")");
    OperationFuture<Database, CreateDatabaseMetadata> op = dbAdminClient.createDatabase(
        db.getInstanceId().getInstance(),
        db.getDatabase(),
        statements);
    try {
      Database dbOperation = op.get();
      System.out.println("Created Spanner database [" + dbOperation.