1. بررسی اجمالی
Spanner یک سرویس پایگاه داده کاملاً مدیریت شده، مقیاس پذیر افقی و توزیع شده در سطح جهانی است که برای بارهای کاری عملیاتی رابطه ای و غیر رابطه ای عالی است. فراتر از قابلیتهای اصلی، Spanner ویژگیهای پیشرفته قدرتمندی را ارائه میکند که امکان ساخت برنامههای هوشمند و مبتنی بر داده را فراهم میکند.
این نرم افزار کد مبتنی بر درک اساسی از Spanner است و با استفاده از یک برنامه بانکداری آنلاین به عنوان پایه، از ادغام های پیشرفته آن برای تقویت پردازش داده ها و قابلیت های تحلیلی شما استفاده می کند.
ما بر روی سه ویژگی پیشرفته کلیدی تمرکز خواهیم کرد:
- ادغام Vertex AI : نحوه ادغام یکپارچه Spanner با پلتفرم هوش مصنوعی Google Cloud، Vertex AI را کشف کنید. شما یاد خواهید گرفت که چگونه مدلهای Vertex AI را مستقیماً از درون پرسوجوهای Spanner SQL فراخوانی کنید، تبدیلها و پیشبینیهای قدرتمند درون پایگاه داده را ممکن میکند، به برنامه بانکی ما اجازه میدهد تا به طور خودکار تراکنشها را برای موارد استفاده مانند ردیابی بودجه و تشخیص ناهنجاری دستهبندی کند.
- جستجوی متن کامل : نحوه پیادهسازی عملکرد جستجوی متن کامل را در Spanner بیاموزید. شما فهرستبندی دادههای متنی و نوشتن پرس و جوهای کارآمد را برای انجام جستجوهای مبتنی بر کلیدواژه در دادههای عملیاتی خود کاوش خواهید کرد، که امکان کشف دادههای قدرتمند را فراهم میکند، مانند یافتن کارآمد مشتریان از طریق آدرس ایمیل در سیستم بانکی ما.
- پرس و جوهای فدرال شده BigQuery : نحوه استفاده از قابلیت های جستجوی فدرال Spanner برای پرس و جو مستقیم داده های موجود در BigQuery را بررسی کنید. این به شما امکان میدهد دادههای عملیاتی بیدرنگ Spanner را با مجموعه دادههای تحلیلی BigQuery برای بینشهای جامع و گزارشدهی بدون تکرار دادهها یا فرآیندهای پیچیده ETL ترکیب کنید، و موارد استفاده مختلف را در برنامههای بانکی ما مانند کمپینهای بازاریابی هدفمند با ترکیب دادههای بیدرنگ مشتری با روندهای تاریخی گستردهتر از BigQuery تقویت کنید.
چیزی که یاد خواهید گرفت
- نحوه راه اندازی یک نمونه Spanner.
- نحوه ایجاد پایگاه داده و جداول
- چگونه داده ها را در جداول پایگاه داده Spanner بارگیری کنیم.
- نحوه فراخوانی مدل های Vertex AI از Spanner.
- چگونه با استفاده از جستجوی فازی و جستجوی متن کامل، پایگاه داده Spanner خود را پرس و جو کنید.
- نحوه انجام کوئری های فدرال در برابر Spanner از BigQuery.
- چگونه نمونه Spanner خود را حذف کنیم.
آنچه شما نیاز دارید
2. راه اندازی و الزامات
یک پروژه ایجاد کنید
اگر قبلاً یک پروژه Google Cloud با فعال کردن صورتحساب دارید، روی منوی کشویی انتخاب پروژه در سمت چپ بالای کنسول کلیک کنید:
با یک پروژه انتخابی، به فعال کردن APIهای مورد نیاز بروید.
اگر قبلاً یک حساب Google (Gmail یا Google Apps) ندارید، باید یک حساب ایجاد کنید . به کنسول Google Cloud Platform ( consol.cloud.google.com ) وارد شوید و یک پروژه جدید ایجاد کنید.
برای ایجاد یک پروژه جدید، روی دکمه "پروژه جدید" در گفتگوی حاصل کلیک کنید:
اگر قبلاً پروژه ای ندارید، باید یک دیالوگ مانند این را ببینید تا اولین پروژه خود را ایجاد کنید:
گفتگوی بعدی ایجاد پروژه به شما امکان می دهد جزئیات پروژه جدید خود را وارد کنید.
شناسه پروژه را به خاطر بسپارید، که یک نام منحصر به فرد در تمام پروژه های Google Cloud است. بعداً در این آزمایشگاه کد به عنوان PROJECT_ID
نامیده خواهد شد.
سپس، اگر قبلاً این کار را انجام ندادهاید، باید صورتحساب را در Developers Console فعال کنید تا از منابع Google Cloud استفاده کنید و Spanner API ، Vertex AI API ، BigQuery API و BigQuery Connection API را فعال کنید.
قیمت آچار در اینجا مستند شده است. سایر هزینه های مرتبط با منابع دیگر در صفحات قیمت گذاری خاص آنها ثبت می شود.
کاربران جدید Google Cloud Platform واجد شرایط استفاده آزمایشی رایگان 300 دلاری هستند.
Google Cloud Shell Setup
در این لبه کد ما از Google Cloud Shell استفاده خواهیم کرد، یک محیط خط فرمان که در Cloud اجرا می شود.
این ماشین مجازی مبتنی بر دبیان با تمام ابزارهای توسعه که شما نیاز دارید بارگذاری شده است. این یک فهرست اصلی 5 گیگابایتی دائمی ارائه میکند و در Google Cloud اجرا میشود، که عملکرد و احراز هویت شبکه را بسیار افزایش میدهد. این بدان معناست که تنها چیزی که برای این کد لبه نیاز دارید یک مرورگر است.
برای فعال کردن Cloud Shell از Cloud Console، کافی است روی Activate Cloud Shell کلیک کنید. (تهیه و اتصال به محیط فقط چند لحظه طول می کشد).
پس از اتصال به Cloud Shell، باید ببینید که قبلاً احراز هویت شده اید و پروژه قبلاً روی PROJECT_ID
شما تنظیم شده است.
gcloud auth list
خروجی مورد انتظار:
Credentialed Accounts ACTIVE: * ACCOUNT: <myaccount>@<mydomain>.com
gcloud config list project
خروجی مورد انتظار:
[core] project = <PROJECT_ID>
اگر به دلایلی پروژه تنظیم نشد، دستور زیر را صادر کنید:
gcloud config set project <PROJECT_ID>
به دنبال PROJECT_ID
خود هستید؟ بررسی کنید از چه شناسه ای در مراحل راه اندازی استفاده کرده اید یا آن را در داشبورد Cloud Console جستجو کنید:
Cloud Shell همچنین برخی از متغیرهای محیطی را به صورت پیشفرض تنظیم میکند که ممکن است هنگام اجرای دستورات آینده مفید باشند.
echo $GOOGLE_CLOUD_PROJECT
خروجی مورد انتظار:
<PROJECT_ID>
API های مورد نیاز را فعال کنید
API های Spanner، Vertex AI و BigQuery را برای پروژه خود فعال کنید:
gcloud services enable spanner.googleapis.com
gcloud services enable aiplatform.googleapis.com
gcloud services enable bigquery.googleapis.com
gcloud services enable bigqueryconnection.googleapis.com
خلاصه
در این مرحله، اگر پروژه خود را نداشتید، پروژه خود را راه اندازی کرده اید، Cloud Shell را فعال کرده اید و API های مورد نیاز را فعال کرده اید.
بعدی
در مرحله بعد، نمونه Spanner را تنظیم خواهید کرد.
3. یک نمونه Spanner را راه اندازی کنید
نمونه Spanner را ایجاد کنید
در این مرحله، یک نمونه Spanner برای Codelab راه اندازی می کنید. برای انجام این کار، Cloud Shell را باز کنید و این دستور را اجرا کنید:
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
خروجی مورد انتظار:
Creating instance...done.
خلاصه
در این مرحله شما نمونه Spanner را ایجاد کرده اید.
بعدی
در مرحله بعد، برنامه اولیه را آماده کرده و پایگاه داده و طرحواره را ایجاد می کنید.
4. یک پایگاه داده و طرحواره ایجاد کنید
درخواست اولیه را آماده کنید
در این مرحله از طریق کد دیتابیس و schema را ایجاد می کنید.
ابتدا یک برنامه جاوا به نام onlinebanking
با استفاده از 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
فایل های داده ای را که به پایگاه داده اضافه می کنیم بررسی و کپی کنید (برای مخزن کد اینجا را ببینید):
git clone https://github.com/GoogleCloudPlatform/cloud-spanner-samples.git
cp -r ./cloud-spanner-samples/banking/data ./onlinebanking
به پوشه برنامه بروید:
cd onlinebanking
فایل Maven pom.xml
را باز کنید. برای استفاده از Maven BOM برای مدیریت نسخه کتابخانههای 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>
ویرایشگر و فایل به این صورت است:
مطمئن شوید که بخش dependencies
شامل کتابخانه هایی است که برنامه استفاده می کند:
<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>
در نهایت، افزونه های ساخت را جایگزین کنید تا برنامه در یک JAR قابل اجرا بسته بندی شود:
<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>
با انتخاب «ذخیره» در منوی «فایل» ویرایشگر Cloud Shell یا با فشار دادن Ctrl+S
تغییراتی را که در فایل pom.xml
ایجاد کردهاید، ذخیره کنید.
اکنون که وابستگیها آماده هستند، کدی را به برنامه اضافه میکنید تا یک طرحواره، برخی فهرستها (از جمله جستجو) و یک مدل هوش مصنوعی متصل به یک نقطه پایانی راه دور ایجاد کنید. شما بر روی این مصنوعات ساخته خواهید شد و متدهای بیشتری را به این کلاس در امتداد این کد لبه اضافه خواهید کرد.
App.java
در آدرس onlinebanking/src/main/java/com/google/codelabs
باز کنید و کد زیر را جایگزین محتوا کنید:
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.getId() + "]");
} catch (ExecutionException e) {
throw (SpannerException) e.getCause();
} catch (InterruptedException e) {
throw SpannerExceptionFactory.propagateInterrupt(e);
}
}
static void printUsageAndExit() {
System.out.println("Online Online Banking Application 1.0.0");
System.out.println("Usage:");
System.out.println(" java -jar target/onlinebanking.jar <command> [command_option(s)]");
System.out.println("");
System.out.println("Examples:");
System.out.println(" java -jar target/onlinebanking.jar create");
System.out.println(" - Create a sample Spanner database and schema in your "
+ "project.\n");
System.exit(1);
}
public static void main(String[] args) {
if (args.length < 1) {
printUsageAndExit();
}
String instanceId = System.getProperty("SPANNER_INSTANCE", System.getenv("SPANNER_INSTANCE"));
String databaseId = System.getProperty("SPANNER_DATABASE", System.getenv("SPANNER_DATABASE"));
String location = System.getenv().getOrDefault("SPANNER_LOCATION", "us-central1");
String model = System.getenv().getOrDefault("SPANNER_MODEL", "gemini-2.0-flash-lite");
if (instanceId == null || databaseId == null) {
System.err.println("Missing one or more required environment variables: SPANNER_INSTANCE or "
+ "SPANNER_DATABASE");
System.exit(1);
}
BigQueryOptions bigqueryOptions = BigQueryOptions.newBuilder().build();
BigQuery bigquery = bigqueryOptions.getService();
SpannerOptions spannerOptions = SpannerOptions.newBuilder().build();
try (Spanner spanner = spannerOptions.getService()) {
String command = args[0];
DatabaseId db = DatabaseId.of(spannerOptions.getProjectId(), instanceId, databaseId);
DatabaseClient dbClient = spanner.getDatabaseClient(db);
DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient();
switch (command) {
case "create":
create(dbAdminClient, db, location, model);
break;
default:
printUsageAndExit();
}
}
}
}
تغییرات را در App.java
ذخیره کنید.
به موجودیت های مختلفی که کد شما ایجاد می کند نگاه کنید و برنامه JAR را بسازید:
mvn package
خروجی مورد انتظار:
[INFO] Building jar: /home/your_user/onlinebanking/target/onlinebanking.jar [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS
برای مشاهده اطلاعات استفاده، برنامه را اجرا کنید:
java -jar target/onlinebanking.jar
خروجی مورد انتظار:
Online Banking Application 1.0.0 Usage: java -jar target/onlinebanking.jar <command> [command_option(s)] Examples: java -jar target/onlinebanking.jar create - Create a sample Spanner database and schema in your project.
پایگاه داده و طرحواره ایجاد کنید
متغیرهای محیط برنامه مورد نیاز را تنظیم کنید:
export SPANNER_INSTANCE=cloudspanner-onlinebanking
export SPANNER_DATABASE=onlinebanking
با اجرای دستور create
دیتابیس و طرحواره را ایجاد کنید:
java -jar target/onlinebanking.jar create
خروجی مورد انتظار:
Creating Spanner database... Created Spanner database [<DATABASE_RESOURCE_NAME>]
طرحواره را در Spanner بررسی کنید
در کنسول Spanner ، به نمونه و پایگاه داده خود که به تازگی ایجاد شده است بروید.
شما باید هر 3 جدول - Accounts
، Customers
و TransactionLedger
را ببینید.
این اقدام طرح پایگاه داده شامل جداول Accounts
، Customers
و TransactionLedger
را به همراه فهرستهای ثانویه برای بازیابی بهینه دادهها و مرجع مدل Vertex AI ایجاد میکند.
جدول TransactionLedger
در حسابها قرار میگیرد تا عملکرد پرس و جو را برای تراکنشهای خاص حساب از طریق بهبود موقعیت دادهها افزایش دهد.
نمایههای ثانویه ( CustomersByEmail
، CustomersFuzzyEmail
، AccountsByCustomer
، TransactionLedgerByAccountType
، TransactionLedgerByCategory
، TransactionLedgerTextSearch
) برای بهینهسازی الگوهای دسترسی به دادههای رایج مورد استفاده در این نرمافزارهای ایمیل کدنویسی و جستجوی مجدد مشتری، از قبیل جستجوی مجدد اکانت مشتری، الگوهای دسترسی به دادههای رایج استفاده شده است. و پرس و جو و جستجوی موثر داده های تراکنش.
TransactionCategoryModel
از Vertex AI برای فعال کردن تماسهای مستقیم SQL به یک LLM استفاده میکند که برای دستهبندی تراکنشهای پویا در این Codelab استفاده میشود.
خلاصه
در این مرحله شما پایگاه داده و طرحواره Spanner را ایجاد کرده اید.
بعدی
در مرحله بعد، داده های نمونه برنامه را بارگیری می کنید.
5. داده ها را بارگذاری کنید
اکنون، عملکردی را برای بارگیری داده های نمونه از فایل های CSV در پایگاه داده اضافه خواهید کرد.
App.java
را باز کنید و با جایگزین کردن importها شروع کنید:
package com.google.codelabs;
import java.io.FileReader;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.Timestamp;
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.Key;
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.cloud.spanner.Statement;
import com.google.cloud.spanner.Struct;
import com.google.spanner.admin.database.v1.CreateDatabaseMetadata;
import com.opencsv.CSVReader;
سپس متدهای insert را به کلاس App
اضافه کنید:
// Insert customers from CSV
public static void insertCustomers(DatabaseClient dbClient) {
System.out.println("Inserting customers...");
dbClient
.readWriteTransaction()
.run(transaction -> {
int count = 0;
List<Statement> statements = new ArrayList<>();
try (CSVReader reader = new CSVReader(new FileReader("data/customers.csv"))) {
reader.skip(1);
String[] line;
while ((line = reader.readNext()) != null) {
Statement statement = Statement.newBuilder(
"INSERT INTO Customers (CustomerId, FirstName, LastName, Email, Address) "
+ "VALUES (@customerId, @firstName, @lastName, @email, @address)")
.bind("customerId").to(Long.parseLong(line[0]))
.bind("firstName").to(line[1])
.bind("lastName").to(line[2])
.bind("email").to(line[3])
.bind("address").to(line[4])
.build();
statements.add(statement);
count++;
}
transaction.batchUpdate(statements);
System.out.println("Inserted " + count + " customers");
return null;
}
});
}
// Insert accounts from CSV
public static void insertAccounts(DatabaseClient dbClient) {
System.out.println("Inserting accounts...");
dbClient
.readWriteTransaction()
.run(transaction -> {
int count = 0;
List<Statement> statements = new ArrayList<>();
try (CSVReader reader = new CSVReader(new FileReader("data/accounts.csv"))) {
reader.skip(1);
String[] line;
while ((line = reader.readNext()) != null) {
Statement statement = Statement.newBuilder(
"INSERT INTO Accounts (AccountId, CustomerId, AccountType, Balance, OpenDate) "
+ "VALUES (@accountId, @customerId, @accountType, @balance, @openDate)")
.bind("accountId").to(Long.parseLong(line[0]))
.bind("customerId").to(Long.parseLong(line[1]))
.bind("accountType").to(line[2])
.bind("balance").to(new BigDecimal(line[3]))
.bind("openDate").to(line[4])
.build();
statements.add(statement);
count++;
}
transaction.batchUpdate(statements);
System.out.println("Inserted " + count + " accounts");
return null;
}
});
}
// Insert transactions from CSV
public static void insertTransactions(DatabaseClient dbClient) {
System.out.println("Inserting transactions...");
dbClient
.readWriteTransaction()
.run(transaction -> {
int count = 0;
List<Statement> statements = new ArrayList<>();
try (CSVReader reader = new CSVReader(new FileReader("data/transactions.csv"))) {
reader.skip(1);
String[] line;
// Specify timestamps that are within last 30 days
Random random = new Random();
Instant startTime = Instant.now().minus(15, ChronoUnit.DAYS);
Instant currentTimestamp = startTime;
Map<Long, BigDecimal> balanceChanges = new HashMap<>();
while ((line = reader.readNext()) != null) {
long accountId = Long.parseLong(line[1]);
String transactionType = line[2];
BigDecimal amount = new BigDecimal(line[3]);
int randomMinutes = random.nextInt(60) + 1;
currentTimestamp = currentTimestamp.plus(Duration.ofMinutes(randomMinutes));
Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(
currentTimestamp.getEpochSecond(), currentTimestamp.getNano());
Statement statement = Statement.newBuilder(
"INSERT INTO TransactionLedger (TransactionId, AccountId, TransactionType, Amount,"
+ "Timestamp, Category, Description) "
+ "VALUES (@transactionId, @accountId, @transactionType, @amount, @timestamp,"
+ "@category, @description)")
.bind("transactionId").to(Long.parseLong(line[0]))
.bind("accountId").to(accountId)
.bind("transactionType").to(transactionType)
.bind("amount").to(amount)
.bind("timestamp").to(timestamp)
.bind("category").to(line[5])
.bind("description").to(line[6])
.build();
statements.add(statement);
// Track balance changes per account
BigDecimal balanceChange = balanceChanges.getOrDefault(accountId,
BigDecimal.ZERO);
if ("Credit".equalsIgnoreCase(transactionType)) {
balanceChanges.put(accountId, balanceChange.add(amount));
} else if ("Debit".equalsIgnoreCase(transactionType)) {
balanceChanges.put(accountId, balanceChange.subtract(amount));
} else {
System.err.println("Unsupported transaction type: " + transactionType);
continue;
}
count++;
}
// Apply final balance updates
for (Map.Entry<Long, BigDecimal> entry : balanceChanges.entrySet()) {
long accountId = entry.getKey();
BigDecimal balanceChange = entry.getValue();
Struct row = transaction.readRow(
"Accounts",
Key.of(accountId),
List.of("Balance"));
if (row != null) {
BigDecimal currentBalance = row.getBigDecimal("Balance");
BigDecimal updatedBalance = currentBalance.add(balanceChange);
Statement statement = Statement.newBuilder(
"UPDATE Accounts SET Balance = @balance WHERE AccountId = @accountId")
.bind("accountId").to(accountId)
.bind("balance").to(updatedBalance)
.build();
statements.add(statement);
}
}
transaction.batchUpdate(statements);
System.out.println("Inserted " + count + " transactions");
}
return null;
});
}
عبارت case دیگری را در متد main
برای درج در switch (command)
اضافه کنید:
case "insert":
String insertType = (args.length >= 2) ? args[1] : "";
if (insertType.equals("customers")) {
insertCustomers(dbClient);
} else if (insertType.equals("accounts")) {
insertAccounts(dbClient);
} else if (insertType.equals("transactions")) {
insertTransactions(dbClient);
} else {
insertCustomers(dbClient);
insertAccounts(dbClient);
insertTransactions(dbClient);
}
break;
در نهایت نحوه استفاده از insert را به متد printUsageAndExit
اضافه کنید:
System.out.println(" java -jar target/onlinebanking.jar insert");
System.out.println(" - Insert sample Customers, Accounts, and Transactions into the "
+ "database.\n");
تغییراتی را که در App.java
ایجاد کردید ذخیره کنید.
برنامه را بازسازی کنید:
mvn package
داده های نمونه را با اجرای دستور insert
وارد کنید:
java -jar target/onlinebanking.jar insert
خروجی مورد انتظار:
Inserting customers... Inserted 100 customers Inserting accounts... Inserted 125 accounts Inserting transactions... Inserted 200 transactions
در کنسول Spanner ، برای نمونه و پایگاه داده خود به Spanner Studio برگردید. سپس جدول TransactionLedger
را انتخاب کنید و روی "داده" در نوار کناری کلیک کنید تا تأیید شود که داده ها بارگذاری شده اند. در جدول باید 200 ردیف وجود داشته باشد.
خلاصه
در این مرحله داده های نمونه را در پایگاه داده وارد کردید.
بعدی
در مرحله بعد، از ادغام Vertex AI برای دستهبندی خودکار تراکنشهای بانکی مستقیماً در Spanner SQL استفاده میکنید.
6. داده ها را با Vertex AI دسته بندی کنید
در این مرحله، از قدرت Vertex AI برای دسته بندی خودکار تراکنش های مالی خود به طور مستقیم در Spanner SQL استفاده می کنید. با Vertex AI می توانید یک مدل از پیش آموزش دیده یا آموزش را انتخاب کنید و مدل خود را مستقر کنید. مدل های موجود را در Vertex AI Model Garden ببینید.
برای این نرم افزار از یکی از مدل های Gemini، Gemini Flash Lite
استفاده می کنیم. این نسخه از Gemini مقرون به صرفه است، اما هنوز هم می تواند بسیاری از کارهای روزانه را تحمل کند.
در حال حاضر، تعدادی تراکنش مالی داریم که میخواهیم بسته به توضیحات، آنها را دستهبندی کنیم ( groceries
، transportation
و غیره). ما می توانیم این کار را با ثبت یک مدل در Spanner و سپس استفاده از ML.PREDICT
برای فراخوانی مدل AI انجام دهیم.
در برنامه بانکی خود ممکن است بخواهیم تراکنشها را دستهبندی کنیم تا بینش عمیقتری درباره رفتار مشتری به دست آوریم تا بتوانیم خدمات را شخصیسازی کنیم، ناهنجاریها را بهطور مؤثرتری شناسایی کنیم، یا به مشتری توانایی ردیابی ماه به ماه بودجه خود را ارائه دهیم.
اولین مرحله از قبل انجام شده بود که ما پایگاه داده و طرحواره را ایجاد کردیم، که مدلی مانند این ایجاد کرد:
در مرحله بعد، روشی را برای فراخوانی ML.PREDICT
به برنامه اضافه می کنیم.
App.java
را باز کنید و متد categorize
اضافه کنید:
// Use Vertex AI to set the category of transactions
public static void categorize(DatabaseClient dbClient) {
System.out.println("Categorizing transactions...");
try {
// Create a prompt to instruct the LLM how to categorize the transactions
String categories = String.join(", ", Arrays.asList("Entertainment", "Gifts", "Groceries",
"Investment", "Medical", "Movies", "Online Shopping", "Other", "Purchases", "Refund",
"Restaurants", "Salary", "Transfer", "Transportation", "Utilities"));
String prompt = "Categorize the following financial activity into one of these "
+ "categories: " + categories + ". Return Other if the description cannot be mapped to "
+ "one of these categories. Only return the exact category string, no other text or "
+ "punctuation or reasoning. Description: ";
String sql = "UPDATE TransactionLedger SET Category = (\n"
+ " SELECT content FROM ML.PREDICT(MODEL `TransactionCategoryModel`, (\n"
+ " SELECT CONCAT('" + prompt + "', CASE WHEN TRIM(Description) = ''\n"
+ " THEN 'Other' ELSE Description END) AS prompt\n"
+ " ))\n"
+ ") WHERE TRUE";
// Use partitioned update to batch update a large number of rows
dbClient.executePartitionedUpdate(Statement.of(sql));
System.out.println("Completed categorizing transactions");
} catch (SpannerException e) {
throw e;
}
}
برای دسته بندی عبارت case دیگری در متد main
اضافه کنید:
case "categorize":
categorize(dbClient);
break;
در نهایت نحوه استفاده از دسته بندی را به متد printUsageAndExit
اضافه کنید:
System.out.println(" java -jar target/onlinebanking.jar categorize");
System.out.println(" - Use AI to categorize transactions in the database.\n");
تغییراتی را که در App.java
ایجاد کردید ذخیره کنید.
برنامه را بازسازی کنید:
mvn package
با اجرای دستور categorize
تراکنش های موجود در پایگاه داده را دسته بندی کنید:
java -jar target/onlinebanking.jar categorize
خروجی مورد انتظار:
Categorizing transactions... Completed categorizing transactions
در Spanner Studio، عبارت Preview Data را برای جدول TransactionLedger
اجرا کنید. اکنون باید ستون Category
برای تمام سطرها پر شود.
اکنون که تراکنشهایی را دستهبندی کردهایم که میتوانیم از این اطلاعات برای پرس و جوهای داخلی یا مشتری استفاده کنیم، در مرحله بعدی به نحوه یافتن میزان هزینه یک مشتری در یک دسته در طول ماه نگاه خواهیم کرد.
خلاصه
در این مرحله، شما از یک مدل از پیش آموزشدیده برای دستهبندی دادههای خود با هوش مصنوعی استفاده کردید.
بعدی
در مرحله بعد، از توکن سازی برای انجام جستجوهای فازی و متن کامل استفاده خواهید کرد.
7. پرس و جو با استفاده از جستجوی متن کامل
کد پرس و جو را اضافه کنید
Spanner بسیاری از عبارت های جستجوی متن کامل را ارائه می دهد. در این مرحله شما یک جستجوی تطابق دقیق انجام میدهید، سپس یک جستجوی فازی و یک جستجوی تمام متن را انجام میدهید.
App.java
را باز کنید و با جایگزین کردن importها شروع کنید:
package com.google.codelabs;
import java.io.FileReader;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.Timestamp;
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.Key;
import com.google.cloud.spanner.ReadOnlyTransaction;
import com.google.cloud.spanner.ResultSet;
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.cloud.spanner.Statement;
import com.google.cloud.spanner.Struct;
import com.google.cloud.spanner.TimestampBound;
import com.google.spanner.admin.database.v1.CreateDatabaseMetadata;
import com.opencsv.CSVReader;
سپس متدهای پرس و جو را اضافه کنید:
// Get current account balance(s) by customer
public static void getBalance(DatabaseClient dbClient, long customerId) {
String query = "SELECT AccountId, Balance\n"
+ "FROM Accounts\n"
+ "WHERE CustomerId = @customerId";
Statement statement = Statement.newBuilder(query)
.bind("customerId").to(customerId)
.build();
// Ignore ongoing transactions, use stale reads as seconds-old data is sufficient
TimestampBound stalenessBound = TimestampBound.ofMaxStaleness(5, TimeUnit.SECONDS);
try (ReadOnlyTransaction transaction = dbClient.singleUseReadOnlyTransaction(stalenessBound);
ResultSet resultSet = transaction.executeQuery(statement);) {
System.out.println("Account balances for customer " + customerId + ":");
while (resultSet.next()) {
System.out.println(" Account " + resultSet.getLong("AccountId") + ": "
+ resultSet.getBigDecimal("Balance"));
}
}
}
// Find customers by email
public static void findCustomers(DatabaseClient dbClient, String email) {
// Query using fuzzy search (ngrams) to allow for spelling mistakes
String query = "SELECT CustomerId, Email\n"
+ "FROM Customers\n"
+ "WHERE SEARCH_NGRAMS(EmailTokens, @email)\n"
+ "ORDER BY SCORE_NGRAMS(EmailTokens, @email) DESC\n"
+ "LIMIT 10";
Statement statement = Statement.newBuilder(query)
.bind("email").to(email)
.build();
try (ReadOnlyTransaction transaction = dbClient.singleUseReadOnlyTransaction();
ResultSet resultSet = transaction.executeQuery(statement)) {
System.out.println("Customer emails matching " + email + " (top 10 matches):");
while (resultSet.next()) {
System.out.println(" Customer " + resultSet.getLong("CustomerId") + ": "
+ resultSet.getString("Email"));
}
}
}
// Get total monthly spending for a customer by category
public static void getSpending(DatabaseClient dbClient, long customerId, String category) {
// Query category using full-text search
String query = "SELECT SUM(Amount) as TotalSpending\n"
+ "FROM TransactionLedger t\n"
+ "JOIN Accounts a\n"
+ " ON t.AccountId = a.AccountId\n"
+ "WHERE t.TransactionType = 'Debit'\n"
+ " AND a.CustomerId = @customerId\n"
+ " AND t.Timestamp >= TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL -30 DAY)\n"
+ " AND (SEARCH(t.CategoryTokens, @category) OR SEARCH(t.DescriptionTokens, @category))";
Statement statement = Statement.newBuilder(query)
.bind("customerId").to(customerId)
.bind("category").to(category)
.build();
try (ReadOnlyTransaction transaction = dbClient.singleUseReadOnlyTransaction();
ResultSet resultSet = transaction.executeQuery(statement);) {
System.out.println("Total spending for customer " + customerId + " under category "
+ category + ":");
while (resultSet.next()) {
BigDecimal totalSpending = BigDecimal.ZERO;
if (!resultSet.isNull("TotalSpending")) {
totalSpending = resultSet.getBigDecimal("TotalSpending");
}
System.out.println(" " + totalSpending);
}
}
}
عبارت case
دیگری را در متد main
برای query اضافه کنید:
case "query":
String queryType = (args.length >= 2) ? args[1] : "";
if (queryType.equals("balance")) {
long customerId = (args.length >= 3) ? Long.parseLong(args[2]) : 1L;
getBalance(dbClient, customerId);
} else if (queryType.equals("email")) {
String email = (args.length >= 3) ? args[2] : "";
findCustomers(dbClient, email);
} else if (queryType.equals("spending")) {
long customerId = (args.length >= 3) ? Long.parseLong(args[2]) : 1L;
String category = (args.length >= 4) ? args[3] : "";
getSpending(dbClient, customerId, category);
} else {
printUsageAndExit();
}
break;
در نهایت نحوه استفاده از دستورات query را به متد printUsageAndExit
اضافه کنید:
System.out.println(" java -jar target/onlinebanking.jar query balance 1");
System.out.println(" - Query customer account balance(s) by customer id.\n");
System.out.println(" java -jar target/onlinebanking.jar query email madi");
System.out.println(" - Find customers by email using fuzzy search.\n");
System.out.println(" java -jar target/onlinebanking.jar query spending 1 groceries");
System.out.println(" - Query customer spending by customer id and category using "
+ "full-text search.\n");
تغییراتی را که در App.java
ایجاد کردید ذخیره کنید.
برنامه را بازسازی کنید:
mvn package
برای موجودی حساب مشتری جستجوی دقیق مطابقت انجام دهید
یک پرس و جو با تطابق دقیق به دنبال ردیف های منطبق است که دقیقاً با یک عبارت مطابقت دارند.
برای بهبود عملکرد، زمانی که پایگاه داده و طرحواره را ایجاد کردید، یک نمایه اضافه شده است:
"CREATE INDEX AccountsByCustomer\n" + "ON Accounts (CustomerId)",
روش getBalance
به طور ضمنی از این شاخص برای یافتن مشتریانی استفاده می کند که با شناسه مشتری ارائه شده مطابقت دارند و همچنین به حساب های متعلق به آن مشتری می پیوندد.
این همان چیزی است که پرس و جو هنگام اجرای مستقیم در Spanner Studio به نظر می رسد:
موجودی حساب مشتری 1
را با اجرای دستور فهرست کنید:
java -jar target/onlinebanking.jar query balance 1
خروجی مورد انتظار:
Account balances for customer 1: Account 1: 9875.25 Account 7: 9900 Account 110: 38200
100 مشتری وجود دارد، بنابراین میتوانید با مشخص کردن یک شناسه مشتری دیگر، موجودی حساب مشتری دیگر را نیز پرس و جو کنید:
java -jar target/onlinebanking.jar query balance 5
java -jar target/onlinebanking.jar query balance 10
java -jar target/onlinebanking.jar query balance 99
یک جستجوی فازی در برابر ایمیل های مشتری انجام دهید
جستجوهای فازی امکان یافتن تطابق تقریبی برای عبارات جستجو، از جمله تغییرات املایی و اشتباهات املایی را فراهم می کند.
هنگامی که پایگاه داده و طرحواره را ایجاد کردید، یک شاخص n-gram قبلاً اضافه شده است:
CREATE TABLE Customers ( ... EmailTokens TOKENLIST AS (TOKENIZE_SUBSTRING(Email, ngram_size_min=>2, ngram_size_max=>3, relative_search_types=>["all"])) HIDDEN, ) PRIMARY KEY(CustomerId); CREATE SEARCH INDEX CustomersFuzzyEmail ON Customers(EmailTokens);
روش findCustomers
از SEARCH_NGRAMS
و SCORE_NGRAMS
برای پرس و جو در برابر این فهرست برای یافتن مشتریان از طریق ایمیل استفاده می کند. از آنجایی که ستون ایمیل n-gram نشانه گذاری شده است، این پرس و جو می تواند حاوی اشتباهات املایی باشد و همچنان پاسخ صحیح را بازگرداند. نتایج بر اساس بهترین تطابق مرتب می شوند.
با اجرای دستور، آدرسهای ایمیل مشتری منطبق را که حاوی madi
هستند پیدا کنید:
java -jar target/onlinebanking.jar query email madi
خروجی مورد انتظار:
Customer emails matching madi (top 10 matches): Customer 39: madison.perez@example.com Customer 64: mason.gray@example.com Customer 91: mabel.alexander@example.com
این پاسخ نزدیکترین موارد منطبق را که شامل madi
یا رشتهای مشابه هستند را به ترتیب رتبهبندی نشان میدهد.
در صورت اجرای مستقیم در Spanner Studio، پرس و جو به این صورت است:
جستجوی فازی همچنین می تواند به اشتباهات املایی مانند غلط املایی emily
کمک کند:
java -jar target/onlinebanking.jar query email emily
java -jar target/onlinebanking.jar query email emliy
java -jar target/onlinebanking.jar query email emilee
خروجی مورد انتظار:
Customer emails matching emliy (top 10 matches): Customer 31: emily.lopez@example.com
در هر مورد، ایمیل مورد انتظار مشتری به عنوان بهترین ضربه برگردانده می شود.
تراکنش ها را با جستجوی تمام متن جستجو کنید
ویژگی جستجوی متن کامل Spanner برای بازیابی رکوردها بر اساس کلمات کلیدی یا عبارات استفاده می شود. قابلیت تصحیح غلط های املایی یا جستجوی مترادف ها را دارد.
هنگامی که پایگاه داده و طرحواره را ایجاد کردید، یک فهرست جستجوی کامل متن قبلاً اضافه شده است:
CREATE TABLE TransactionLedger ( ... CategoryTokens TOKENLIST AS (TOKENIZE_FULLTEXT(Category)) HIDDEN, DescriptionTokens TOKENLIST AS (TOKENIZE_FULLTEXT(Description)) HIDDEN, ) PRIMARY KEY(AccountId, TransactionId), INTERLEAVE IN PARENT Accounts ON DELETE CASCADE; CREATE SEARCH INDEX TransactionLedgerTextSearch ON TransactionLedger(CategoryTokens, DescriptionTokens);
روش getSpending
از تابع جستجوی متن کامل SEARCH
برای مطابقت با آن شاخص استفاده می کند. تمام هزینه ها (بدهی ها) در 30 روز گذشته برای شناسه مشتری داده شده را جستجو می کند.
با اجرای دستور زیر، کل هزینههای یک ماه گذشته برای مشتری 1
در دسته groceries
را دریافت کنید:
java -jar target/onlinebanking.jar query spending 1 groceries
خروجی مورد انتظار:
Total spending for customer 1 under category groceries: 50
همچنین میتوانید هزینهها را در دستههای دیگر (که در مرحله قبل دستهبندی کردیم) پیدا کنید یا از یک شناسه مشتری متفاوت استفاده کنید:
java -jar target/onlinebanking.jar query spending 1 transportation
java -jar target/onlinebanking.jar query spending 1 restaurants
java -jar target/onlinebanking.jar query spending 12 entertainment
خلاصه
در این مرحله، پرس و جوهای تطبیق دقیق و همچنین جستجوهای فازی و متن کامل را انجام دادید.
بعدی
سپس، Spanner را با Google BigQuery ادغام میکنید تا درخواستهای فدرال را انجام دهید، و به شما این امکان را میدهد که دادههای Spanner بلادرنگ خود را با دادههای BigQuery ترکیب کنید.
8. کوئری های فدرال را با BigQuery اجرا کنید
مجموعه داده BigQuery را ایجاد کنید
در این مرحله، داده های BigQuery و Spanner را با استفاده از پرس و جوهای فدرال گرد هم می آورید.
برای انجام این کار، در خط فرمان Cloud Shell، ابتدا یک مجموعه داده MarketingCampaigns
ایجاد کنید:
bq mk --location=us-central1 MarketingCampaigns
خروجی مورد انتظار:
Dataset '<PROJECT_ID>:MarketingCampaigns' successfully created.
و یک جدول CustomerSegments
در مجموعه داده:
bq mk --table MarketingCampaigns.CustomerSegments CampaignId:STRING,CampaignName:STRING,CustomerId:INT64
خروجی مورد انتظار:
Table '<PROJECT_ID>:MarketingCampaigns.CustomerSegments' successfully created.
سپس، از BigQuery به Spanner یک اتصال برقرار کنید:
bq mk --connection \
--connection_type=CLOUD_SPANNER \
--properties="{\"database\": \"projects/$GOOGLE_CLOUD_PROJECT/instances/cloudspanner-onlinebanking/databases/onlinebanking\", \"useParallelism\": true, \"useDataBoost\": true}" \
--location=us-central1 \
spanner-connection
خروجی مورد انتظار:
Connection <PROJECT_NUMBER>.us-central1.spanner-connection successfully created
در نهایت، تعدادی مشتری را به جدول BigQuery اضافه کنید که میتوان آنها را با دادههای Spanner ما ملحق کرد:
bq query --use_legacy_sql=false '
INSERT INTO MarketingCampaigns.CustomerSegments (CampaignId, CampaignName, CustomerId)
VALUES
("campaign1", "Spring Promotion", 1),
("campaign1", "Spring Promotion", 3),
("campaign1", "Spring Promotion", 5),
("campaign1", "Spring Promotion", 7),
("campaign1", "Spring Promotion", 9),
("campaign1", "Spring Promotion", 11)'
خروجی مورد انتظار:
Waiting on bqjob_r76a7ce76c5ec948f_0000019644bda052_1 ... (0s) Current status: DONE Number of affected rows: 6
میتوانید با جستجو در BigQuery تأیید کنید که دادهها در دسترس هستند:
bq query --use_legacy_sql=false "SELECT * FROM MarketingCampaigns.CustomerSegments"
خروجی مورد انتظار:
+------------+------------------+------------+ | CampaignId | CampaignName | CustomerId | +------------+------------------+------------+ | campaign1 | Spring Promotion | 1 | | campaign1 | Spring Promotion | 5 | | campaign1 | Spring Promotion | 7 | | campaign1 | Spring Promotion | 9 | | campaign1 | Spring Promotion | 11 | | campaign1 | Spring Promotion | 3 | +------------+------------------+------------+
این دادهها در BigQuery دادههایی را نشان میدهند که از طریق گردشهای کاری مختلف بانک اضافه شدهاند. به عنوان مثال، این ممکن است لیست مشتریانی باشد که اخیراً حساب باز کرده اند یا برای تبلیغات بازاریابی ثبت نام کرده اند. برای تعیین لیست مشتریانی که میخواهیم در کمپین بازاریابی خود هدف قرار دهیم، باید هم این دادهها را در BigQuery و هم دادههای بلادرنگ را در Spanner پرس و جو کنیم، و یک پرس و جو فدرال به ما این امکان را میدهد که این کار را در یک جستجو انجام دهیم.
یک پرس و جو فدرال را با BigQuery اجرا کنید
در مرحله بعد، روشی را به برنامه اضافه می کنیم تا EXTERNAL_QUERY
را برای انجام پرس و جو فدرال فراخوانی کند. این امکان پیوستن و تجزیه و تحلیل دادههای مشتری را در BigQuery و Spanner فراهم میکند، مانند شناسایی مشتریانی که معیارهای کمپین بازاریابی ما را بر اساس هزینههای اخیرشان برآورده میکنند.
App.java
را باز کنید و با جایگزین کردن importها شروع کنید:
package com.google.codelabs;
import java.io.FileReader;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.Timestamp;
import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.connection.v1.ConnectionName;
import com.google.cloud.bigquery.JobException;
import com.google.cloud.bigquery.QueryJobConfiguration;
import com.google.cloud.bigquery.TableResult;
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.Key;
import com.google.cloud.spanner.ReadOnlyTransaction;
import com.google.cloud.spanner.ResultSet;
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.cloud.spanner.Statement;
import com.google.cloud.spanner.Struct;
import com.google.cloud.spanner.TimestampBound;
import com.google.spanner.admin.database.v1.CreateDatabaseMetadata;
import com.opencsv.CSVReader;
سپس روش campaign
را اضافه کنید:
// Get customers for quarterly marketing campaign in BigQuery using Spanner data
public static void campaign(BigQuery bq, DatabaseId db, String location, String campaignId,
int threshold) {
// The BigQuery dataset, table, and Spanner connection must already exist for this to succeed
ConnectionName connection = ConnectionName.of(db.getInstanceId().getProject(), location,
"spanner-connection");
// Use a federated query to bring Spanner data into BigQuery
String bqQuery = "SELECT cs.CampaignName, c.CustomerId, c.FullName, t.TotalSpending\n"
+ "FROM MarketingCampaigns.CustomerSegments cs\n"
+ "JOIN EXTERNAL_QUERY('" + connection.toString() + "',\n"
+ " \"SELECT t.AccountId, SUM(t.Amount) AS TotalSpending"
+ " FROM TransactionLedger t"
+ " WHERE t.Timestamp >= TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL -90 DAY)"
+ " GROUP BY t.AccountId"
+ " HAVING SUM(t.Amount) > " + threshold + "\"\n"
+ ") t ON cs.CustomerId = t.AccountId\n"
+ "JOIN EXTERNAL_QUERY('" + connection.toString() + "',\n"
+ " \"SELECT CustomerId, FullName"
+ " FROM Customers\"\n"
+ ") c ON c.CustomerId = cs.CustomerId\n"
+ "WHERE cs.CampaignId = '" + campaignId + "'";
try {
QueryJobConfiguration queryConfig = QueryJobConfiguration.newBuilder(bqQuery).build();
TableResult results = bq.query(queryConfig);
System.out.println("Customers for campaign (" + campaignId + "):");
results.iterateAll().forEach(row -> {
System.out.println(" " + row.get("FullName").getStringValue()
+ " (" + row.get("CustomerId").getStringValue() + ")");
});
} catch (JobException e) {
throw (BigQueryException) e.getCause();
} catch (InterruptedException e) {
throw SpannerExceptionFactory.propagateInterrupt(e);
}
}
عبارت case دیگری را در متد main
برای کمپین اضافه کنید:
case "campaign":
String campaignId = (args.length >= 2) ? args[1] : "";
int threshold = (args.length >= 3) ? Integer.parseInt(args[2]) : 5000;
campaign(bigquery, db, location, campaignId, threshold);
break;
در نهایت نحوه استفاده از کمپین را به متد printUsageAndExit
اضافه کنید:
System.out.println(" java -jar target/onlinebanking.jar campaign campaign1 5000");
System.out.println(" - Use Federated Queries (BigQuery) to find customers that match a "
+ "marketing campaign by name based on a recent spending threshold.\n");
تغییراتی را که در App.java
ایجاد کردید ذخیره کنید.
برنامه را بازسازی کنید:
mvn package
برای تعیین اینکه مشتریانی که در طول 3 ماه گذشته حداقل $5000
هزینه کرده اند، با اجرای دستور campaign
، campaign1
پرس و جو فدرال را برای تعیین مشتریانی که باید در کمپین بازاریابی گنجانده شوند، اجرا کنید:
java -jar target/onlinebanking.jar campaign campaign1 5000
خروجی مورد انتظار:
Customers for campaign (campaign1): Alice Smith (1) Eve Davis (5) Kelly Thomas (11)
اکنون می توانیم این مشتریان را با پیشنهادات یا جوایز انحصاری هدف قرار دهیم.
یا میتوانیم به دنبال تعداد بیشتری از مشتریان باشیم که در 3 ماه گذشته به آستانه خرج کمتری دست یافتهاند:
java -jar target/onlinebanking.jar campaign campaign1 2500
خروجی مورد انتظار:
Customers for campaign (campaign1): Alice Smith (1) Charlie Williams (3) Eve Davis (5) Ivy Taylor (9) Kelly Thomas (11)
خلاصه
در این مرحله، پرسوجوهای فدرالشده را از BigQuery که دادههای Spanner بلادرنگ را وارد میکردند، با موفقیت اجرا کردید.
بعدی
در مرحله بعد، میتوانید منابع ایجاد شده برای این کد لبه را پاکسازی کنید تا از پرداخت هزینه جلوگیری کنید.
9. پاکسازی (اختیاری)
این مرحله اختیاری است. اگر میخواهید به آزمایش نمونه Spanner خود ادامه دهید، در حال حاضر نیازی به پاکسازی آن ندارید. با این حال، پروژه ای که از آن استفاده می کنید همچنان برای نمونه هزینه دریافت می کند. اگر دیگر نیازی به این نمونه ندارید، باید در این زمان آن را حذف کنید تا از این هزینه ها جلوگیری کنید. علاوه بر نمونه Spanner، این Codelab همچنین یک مجموعه داده و اتصال BigQuery ایجاد کرد که باید در مواقعی که دیگر مورد نیاز نیستند پاک شوند.
نمونه Spanner را حذف کنید:
gcloud spanner instances delete cloudspanner-onlinebanking
تأیید کنید که میخواهید ادامه دهید ( Y تایپ کنید):
Delete instance [cloudspanner-onlinebanking]. Are you sure? Do you want to continue (Y/n)?
اتصال و مجموعه داده BigQuery را حذف کنید:
bq rm --connection --location=us-central1 spanner-connection
bq rm -r MarketingCampaigns
تأیید حذف مجموعه داده BigQuery (نوع Y ):
rm: remove dataset '<PROJECT_ID>:MarketingCampaigns'? (y/N)
10. تبریک می گویم
🚀 شما یک نمونه Cloud Spanner جدید ایجاد کردهاید، یک پایگاه داده خالی ایجاد کردهاید، دادههای نمونه را بارگیری کردهاید، عملیاتها و جستجوهای پیشرفته را انجام دادهاید، و (به صورت اختیاری) نمونه Cloud Spanner را حذف کردهاید.
آنچه را پوشش داده ایم
- نحوه راه اندازی یک نمونه Spanner.
- نحوه ایجاد پایگاه داده و جداول
- چگونه داده ها را در جداول پایگاه داده Spanner بارگیری کنیم.
- نحوه فراخوانی مدل های Vertex AI از Spanner.
- چگونه با استفاده از جستجوی فازی و جستجوی متن کامل، پایگاه داده Spanner خود را پرس و جو کنید.
- نحوه انجام کوئری های فدرال در برابر Spanner از BigQuery.
- چگونه نمونه Spanner خود را حذف کنیم.
بعدش چی؟
- درباره ویژگیهای پیشرفته Spanner ، از جمله:
- کتابخانه های سرویس گیرنده Spanner موجود را ببینید.