תחילת העבודה עם חיפוש היברידי ב-AlloyDB וב-Apache Solr

1. מבוא

ב-codelab הזה תלמדו איך לבצע חיפוש היברידי ב-AlloyDB באמצעות pgvector ואינדקס Scalable Nearest Neighbor ‏ (ScaNN), בשילוב עם יכולת חיפוש טקסט מלא מ-Apache Solr דרך Foreign Data Wrapper ‏ (FDW). שיעור ה-Lab הזה הוא חלק מאוסף שיעורי Lab שמוקדשים לתכונות AI ב-AlloyDB. מידע נוסף אפשר לקרוא בדף בנושא AlloyDB AI במאמרי העזרה.

‫Apache Solr היא פלטפורמת חיפוש ארגונית בקוד פתוח שמבוססת על Apache Lucene, ומיועדת ליכולת חיפוש מהירה, ניתנת להרחבה וזמינה מאוד של טקסט מלא. שילוב של Solr עם AlloyDB באמצעות Foreign Data Wrapper ‏ (FDW) מאפשר למשתמשים לשלוח שאילתות לאינדקסים של Solr ישירות מ-PostgreSQL, לצד טבלאות של מסדי נתונים מובְנים. מידע נוסף מופיע במאמרי העזרה של Apache Solr.

דרישות מוקדמות

  • הבנה בסיסית של Google Cloud Console
  • מיומנויות בסיסיות בממשק שורת הפקודה וב-Google Shell

מה תלמדו

  • איך פורסים אשכול AlloyDB ומכונה ראשית
  • איך מתחברים ל-AlloyDB ממכונה וירטואלית של Google Compute Engine
  • איך יוצרים מסד נתונים ומפעילים את AlloyDB AI
  • איך טוענים נתונים למסד הנתונים
  • איך משתמשים ב-AlloyDB Studio
  • יצירת הטמעות באמצעות Vertex AI
  • איך יוצרים אינדקס וקטורי של ScaNN כדי לשפר את החיפוש הווקטורי
  • איך יוצרים Foreign Data Wrapper ‏ (FDW) ל-Apache Solr
  • ביצוע חיפוש היברידי על ידי שילוב של חיפוש סמנטי ב-AlloyDB עם חיפוש טקסט מלא ב-Solr.

מה תצטרכו

  • חשבון Google Cloud ופרויקט Google Cloud
  • דפדפן אינטרנט כמו Chrome

2. הגדרה ודרישות

הגדרת פרויקט

נכנסים למסוף Google Cloud. אם עדיין אין לכם חשבון Gmail או Google Workspace, אתם צריכים ליצור חשבון.

משתמשים בחשבון לשימוש אישי במקום בחשבון לצורכי עבודה או בחשבון בית ספרי.

  1. במסוף Google Cloud, בדף לבחירת הפרויקט, בוחרים פרויקט ב-Google Cloud או יוצרים פרויקט.
  2. הקפידו לוודא שהחיוב מופעל בפרויקט שלכם ב-Cloud. כך בודקים אם החיוב מופעל בפרויקט

הפעלת החיוב

יש שתי דרכים להפעיל את החיוב. אתם יכולים להשתמש בחשבון החיוב האישי שלכם או לממש את הקרדיטים באמצעות השלבים הבאים.

הגדרה של חשבון לחיוב לשימוש אישי

אם הגדרתם חיוב באמצעות קרדיטים ב-Google Cloud, אתם יכולים לדלג על השלב הזה.

כדי להגדיר חשבון לחיוב לשימוש אישי, עוברים לכאן כדי להפעיל את החיוב ב-Cloud Console.

הערות:

  • העלות של השלמת ה-Lab הזה במשאבי Cloud צריכה להיות פחות מ-3 דולר ארה"ב.
  • כדי למנוע חיובים נוספים, אפשר למחוק את המשאבים לפי השלבים שמפורטים בסוף ה-Lab הזה.
  • משתמשים חדשים זכאים לתקופת ניסיון בחינם בשווי 300$.

מפעילים את Cloud Shell

אפשר להפעיל את Google Cloud מרחוק מהמחשב הנייד, אבל ב-Codelab הזה נשתמש ב-Google Cloud Shell, סביבת שורת פקודה שפועלת בענן.

‫Cloud Shell היא סביבת שורת פקודה שפועלת ב-Google Cloud וכוללת מראש את הכלים הנדרשים.

  1. לוחצים על Activate Cloud Shell בחלק העליון של מסוף Google Cloud.
  2. אחרי שמתחברים ל-Cloud Shell, מאמתים את האימות:
    gcloud auth list
    
  3. מוודאים שהפרויקט מוגדר:
    gcloud config get project
    
  4. אם הפרויקט לא מוגדר כמו שציפיתם, מגדירים אותו:
    export PROJECT_ID=<YOUR_PROJECT_ID>
    gcloud config set project $PROJECT_ID
    

המכונה הווירטואלית הזו כוללת את כל הכלים שדרושים למפתחים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, מה שמשפר מאוד את הביצועים והאימות ברשת. אפשר לבצע את כל העבודה ב-codelab הזה בדפדפן. לא צריך להתקין שום דבר.

3. לפני שמתחילים

הפעלת ה-API

פלט:

כדי להשתמש ב-AlloyDB, ב-Compute Engine, ב-Networking services וב-Vertex AI, צריך להפעיל את ממשקי ה-API שלהם בפרויקט Google Cloud.

הפעלת ממשקי ה-API

בטרמינל של Cloud Shell, מוודאים שמזהה הפרויקט מוגדר:

gcloud config set project [YOUR-PROJECT-ID]

מגדירים את משתנה הסביבה PROJECT_ID:

PROJECT_ID=$(gcloud config get-value project)

מפעילים את כל ממשקי ה-API הנדרשים:

gcloud services enable alloydb.googleapis.com \
                       compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       aiplatform.googleapis.com \
                       secretmanager.googleapis.com

הפלט הצפוי

student@cloudshell:~ (alloydb-hybrid-search)$ gcloud config set project alloydb-hybrid-search
[environment: untagged] Read more to tag: g.co/cloud/project-env-tag.
Updated property [core/project].
student@cloudshell:~ (alloydb-hybrid-search)$ PROJECT_ID=$(gcloud config get-value project)
Your active configuration is: [cloudshell-32544]
student@cloudshell:~ (alloydb-hybrid-search)$ gcloud services enable alloydb.googleapis.com \
                       compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       aiplatform.googleapis.com \
                       secretmanager.googleapis.com
Operation "operations/acat.p2-350113473377-5ffc2f22-caa9-4857-b2f4-018657d8bf6e" finished successfully.

מבוא לממשקי ה-API

  • ‫AlloyDB API‏ (alloydb.googleapis.com) מאפשר לכם ליצור אשכולות של AlloyDB ל-PostgreSQL, לנהל אותם ולשנות את הגודל שלהם. הוא מספק שירות מנוהל של מסד נתונים שתואם ל-PostgreSQL ומיועד לעומסי עבודה כבדים בטרנזקציות ובניתוחים בארגונים.
  • ‫Compute Engine API‏ (compute.googleapis.com) מאפשר לכם ליצור ולנהל מכונות וירטואליות (VM), דיסקים לאחסון מתמיד והגדרות רשת. היא מספקת את הבסיס של תשתית כשירות (IaaS) שנדרש להפעלת עומסי העבודה ולאירוח התשתית הבסיסית של שירותים מנוהלים רבים.
  • ‫Cloud Resource Manager API‏ (cloudresourcemanager.googleapis.com) מאפשר לכם לנהל באופן פרוגרמטי את המטא-נתונים וההגדרות של פרויקט Google Cloud. היא מאפשרת לכם לארגן משאבים, לטפל במדיניות של ניהול זהויות והרשאות גישה (IAM) ולאמת הרשאות בהיררכיית הפרויקט.
  • ‫Service Networking API ‏ (servicenetworking.googleapis.com) מאפשר לכם להגדיר באופן אוטומטי קישוריות פרטית בין הרשת של הענן הווירטואלי הפרטי (VPC) לבין השירותים המנוהלים של Google. היא נדרשת במיוחד כדי ליצור גישה פרטית ל-IP לשירותים כמו AlloyDB, כדי שהם יוכלו לתקשר בצורה מאובטחת עם המשאבים האחרים שלכם.
  • ‫Vertex AI API‏ (aiplatform.googleapis.com) מאפשר לאפליקציות שלכם ליצור מודלים של למידת מכונה, לפרוס אותם ולבצע להם התאמה לעומס (scaling). הוא מספק ממשק מאוחד לכל שירותי ה-AI של Google Cloud, כולל גישה למודלים של AI גנרטיבי (כמו Gemini) ואימון מודלים בהתאמה אישית.
  • ‫Secret Manager API ‏ (secretmanager.googleapis.com) הוא שירות לניהול סודות ואישורים שמאפשר לכם לאחסן ולנהל מידע אישי רגיש כמו מפתחות API, שמות משתמש, סיסמאות, אישורים ועוד.

אופציונלית, אתם יכולים להגדיר את אזור ברירת המחדל לשימוש במודלים של הטמעת Vertex AI. מידע נוסף על המיקומים שבהם Vertex AI זמין בדוגמה אנחנו משתמשים באזור us-central1.

gcloud config set compute/region us-central1

4. פריסת AlloyDB

לפני שיוצרים אשכול AlloyDB, צריך טווח כתובות IP פרטיות שזמין ב-VPC לשימוש על ידי מכונת AlloyDB עתידית. אם אין לנו את זה, אנחנו צריכים ליצור אותו, להקצות אותו לשימוש בשירותים פנימיים של Google, ואז נוכל ליצור את האשכול ואת המופע.

יצירת טווח כתובות IP פרטיות

אנחנו צריכים להגדיר הגדרת גישה לשירות פרטי ב-VPC שלנו ל-AlloyDB. ההנחה כאן היא שיש לנו רשת VPC 'ברירת מחדל' בפרויקט, והיא תשמש לכל הפעולות.

יוצרים את טווח כתובות ה-IP הפרטיות:

gcloud compute addresses create psa-range \
    --global \
    --purpose=VPC_PEERING \
    --prefix-length=24 \
    --description="VPC private service access" \
    --network=default

יצירת חיבור פרטי באמצעות טווח כתובות ה-IP שהוקצה:

gcloud services vpc-peerings connect \
    --service=servicenetworking.googleapis.com \
    --ranges=psa-range \
    --network=default

אחרי החיבור, מעדכנים את ה-Peering כדי לייצא נתיבים מותאמים אישית:

gcloud compute networks peerings update servicenetworking-googleapis-com \
    --network=default \
    --export-custom-routes

הפלט הצפוי בקונסולה:

student@cloudshell:~ (alloydb-hybrid-search)$ gcloud compute addresses create psa-range \
    --global \
    --purpose=VPC_PEERING \
    --prefix-length=24 \
    --description="VPC private service access" \
    --network=default
Created [https://www.googleapis.com/compute/v1/projects/alloydb-hybrid-search/global/addresses/psa-range].

student@cloudshell:~ (alloydb-hybrid-search)$ gcloud services vpc-peerings connect \
    --service=servicenetworking.googleapis.com \
    --ranges=psa-range \
    --network=default
Operation "operations/pssn.p24-350113473377-fadad49e-7e14-472a-8888-26951e40a1f7" finished successfully.

student@cloudshell:~ (alloydb-hybrid-search)$ gcloud compute networks peerings update servicenetworking-googleapis-com \
    --network=default \
    --export-custom-routes
Updated [https://www.googleapis.com/compute/v1/projects/alloydb-hybrid-search/global/networks/default].

יצירת אשכול AlloyDB

בקטע הזה אנחנו יוצרים אשכול AlloyDB באזור us-central1.

מגדירים סיסמה למשתמש postgres. אתם יכולים להגדיר סיסמה משלכם או להשתמש בפונקציה אקראית כדי ליצור סיסמה

export PGPASSWORD=`openssl rand -hex 12`

הפלט הצפוי בקונסולה:

student@cloudshell:~ (alloydb-hybrid-search)$ export PGPASSWORD=`openssl rand -hex 12`

חשוב לשמור את הסיסמה של PostgreSQL לשימוש עתידי.

echo $PGPASSWORD

תצטרכו את הסיסמה הזו בעתיד כדי להתחבר למופע בתור משתמש postgres. מומלץ להעתיק אותו למיקום מאובטח (למשל, למנהל סיסמאות).

הפלט הצפוי בקונסולה:

student@cloudshell:~ (alloydb-hybrid-search)$ echo $PGPASSWORD
<generated password>

יצירת אשכול AlloyDB

מגדירים את האזור ואת שם אשכול AlloyDB. אנחנו נשתמש באזור us-central1 וב-alloydb-hybrid-search כשם האשכול:

export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search

מריצים את הפקודה ליצירת האשכול:

gcloud alloydb clusters create $ADBCLUSTER \
    --password=$PGPASSWORD \
    --network=default \
    --region=$REGION \
    --database-version=POSTGRES_17

הפלט הצפוי בקונסולה:

student@cloudshell:~ (alloydb-hybrid-search)$ export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search
student@cloudshell:~ (alloydb-hybrid-search)$ gcloud alloydb clusters create $ADBCLUSTER \
    --password=$PGPASSWORD \
    --network=default \
    --region=$REGION \
    --database-version=POSTGRES_17
Creating cluster...done.

יוצרים מכונה ראשית של AlloyDB לאשכול באותו סשן של Cloud Shell. אם החיבור ינותק, תצטרכו להגדיר מחדש את משתני הסביבה של שם האזור ושם האשכול.

gcloud alloydb instances create $ADBCLUSTER-pr \
    --instance-type=PRIMARY \
    --cpu-count=2 \
    --region=$REGION \
    --cluster=$ADBCLUSTER

הפלט הצפוי בקונסולה:

admin_@cloudshell:~ (my-project-93954-gke)$ gcloud alloydb instances create $ADBCLUSTER-pr \
    --instance-type=PRIMARY \
    --cpu-count=2 \
    --region=$REGION \
    --availability-type ZONAL \
    --cluster=$ADBCLUSTER
Operation ID: operation-1784244706986-656c2d7f3c8f2-59a9e52a-1e7b1b01
Creating instance...done.                                                                                                                                                                                                                                                     

5. חיבור ל-AlloyDB

‫AlloyDB נפרס באמצעות חיבור פרטי בלבד, לכן אנחנו צריכים מכונה וירטואלית עם לקוח PostgreSQL מותקן כדי לעבוד עם מסד הנתונים. נשתמש במכונה הווירטואלית הזו גם כדי להריץ מופע של Apache Solr.

Deploy GCE VM

יוצרים מכונה וירטואלית ב-GCE באותו אזור ובאותו VPC כמו אשכול AlloyDB, ומוודאים שדיסק האתחול גדול מספיק להרצת Solr. בדוגמה הזו, אנחנו מציינים דיסק אתחול בנפח 20GB באמצעות הדגל --create-disk.

ב-Cloud Shell, מריצים את הפקודה:

export ZONE=us-central1-a
gcloud compute instances create instance-1 \
    --zone=$ZONE \
    --create-disk=auto-delete=yes,boot=yes,size=20,image=projects/debian-cloud/global/images/$(gcloud compute images list --filter="family=debian-12 AND family!=debian-12-arm64" --format="value(name)") \
    --scopes=https://www.googleapis.com/auth/cloud-platform

הפלט הצפוי בקונסולה:

student@cloudshell:~ (alloydb-hybrid-search)$ export ZONE=us-central1-a
gcloud compute instances create instance-1 \
    --zone=$ZONE \
    --network=default \
    --create-disk=auto-delete=yes,boot=yes,image=projects/debian-cloud/global/images/$(gcloud compute images list --filter="family=debian-12 AND family!=debian-12-arm64" --format="value(name)") \
    --scopes=https://www.googleapis.com/auth/cloud-platform

Created [https://www.googleapis.com/compute/v1/projects/test-project-402417/zones/us-central1-a/instances/instance-1].
NAME: instance-1
ZONE: us-central1-a
MACHINE_TYPE: n1-standard-1
PREEMPTIBLE:
INTERNAL_IP: X.X.X.X
EXTERNAL_IP: X.X.X.X
STATUS: RUNNING

התקנת לקוח Postgres

התקנת תוכנת הלקוח של PostgreSQL במכונה הווירטואלית שנפרסה

מתחברים ל-VM:

gcloud compute ssh instance-1 --zone=us-central1-a

הפלט הצפוי בקונסולה:

admin_@cloudshell:~ (my-project-93954-gke)$ gcloud compute ssh instance-1 --zone=us-central1-a
Updating project ssh metadata...working..Updated [https://www.googleapis.com/compute/v1/projects/alloydb-hybrid-search].                                                                                                                                                         
Updating project ssh metadata...done.                                                                                                                                                                                                                                              
Waiting for SSH key to propagate.
Warning: Permanently added 'compute.5110295539541121102' (ECDSA) to the list of known hosts.
Linux instance-1.us-central1-a.c.gleb-test-short-001-418811.internal 6.1.0-18-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.76-1 (2024-02-01) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

מריצים את פקודת התוכנה בתוך ה-VM:

sudo apt-get update
sudo apt-get install --yes postgresql-client

הפלט הצפוי בקונסולה:

student@instance-1:~$ sudo apt-get update
sudo apt-get install --yes postgresql-client
Get:1 https://packages.cloud.google.com/apt google-compute-engine-bullseye-stable InRelease [5146 B]
Get:2 https://packages.cloud.google.com/apt cloud-sdk-bullseye InRelease [6406 B]   
Hit:3 https://deb.debian.org/debian bullseye InRelease  
Get:4 https://deb.debian.org/debian-security bullseye-security InRelease [48.4 kB]
Get:5 https://packages.cloud.google.com/apt google-compute-engine-bullseye-stable/main amd64 Packages [1930 B]
Get:6 https://deb.debian.org/debian bullseye-updates InRelease [44.1 kB]
Get:7 https://deb.debian.org/debian bullseye-backports InRelease [49.0 kB]
...redacted...
Setting up postgresql-client (15+248+deb12u1) ...
Processing triggers for man-db (2.11.2-2) ...
Processing triggers for libc-bin (2.36-9+deb12u14) ...

התחברות למופע

מתחברים למופע הראשי מהמכונה הווירטואלית באמצעות psql.

בכרטיסייה של Cloud Shell שבה פתוח סשן SSH למכונה הווירטואלית instance-1.

משתמשים בערך הסיסמה (PGPASSWORD) של AlloyDB שרשמתם ובמזהה האשכול של AlloyDB כדי להתחבר ל-AlloyDB מהמכונה הווירטואלית של GCE:

export PGPASSWORD=<Noted password>
export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search
export INSTANCE_IP=$(gcloud alloydb instances describe $ADBCLUSTER-pr --cluster=$ADBCLUSTER --region=$REGION --format="value(ipAddress)")
psql "host=$INSTANCE_IP user=postgres sslmode=require"

הפלט הצפוי בקונסולה:

student@instance-1:~$ export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search
export INSTANCE_IP=$(gcloud alloydb instances describe $ADBCLUSTER-pr --cluster=$ADBCLUSTER --region=$REGION --format="value(ipAddress)")
psql "host=$INSTANCE_IP user=postgres sslmode=require"
psql (15.18 (Debian 15.18-0+deb12u1), server 17.9)
WARNING: psql major version 15, server major version 17.
         Some psql features might not work.
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

postgres=> 

סוגרים את סשן ה-psql:

exit

6. הכנת מסד הנתונים

צריך ליצור מסד נתונים, להפעיל את השילוב עם Vertex AI, ליצור אובייקטים של מסד נתונים ולייבא את הנתונים.

מתן ההרשאות הנדרשות ל-AlloyDB

מוסיפים הרשאות ל-Vertex AI לסוכן השירות של AlloyDB.

פותחים כרטיסייה נוספת ב-Cloud Shell באמצעות הסימן '+' בחלק העליון.

abc1.png

בכרטיסייה החדשה של Cloud Shell, מריצים את הפקודה:

PROJECT_ID=$(gcloud config get-value project)
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \
  --role="roles/aiplatform.user"

הפלט הצפוי בקונסולה:

admin_@cloudshell:~ (my-project-93954-gke)$ PROJECT_ID=$(gcloud config get-value project)
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \
  --role="roles/aiplatform.user"
Your active configuration is: [cloudshell-30137]

Updated IAM policy for project [my-project-93954-gke].
bindings:
- members:
<redacted>
version: 1

סוגרים את הכרטיסייה בלחיצה על X או על ידי הפעלת הפקודה:

exit

יצירת מסד נתונים

יוצרים מסד נתונים בשם quickstart.

בסשן של המכונה הווירטואלית ב-GCE, מריצים את הפקודה:

יצירת מסד נתונים:

psql "host=$INSTANCE_IP user=postgres" -c "CREATE DATABASE quickstart_db"

הפלט הצפוי בקונסולה:

student@instance-1:~$ psql "host=$INSTANCE_IP user=postgres" -c "CREATE DATABASE quickstart_db"
CREATE DATABASE

הפעלת השילוב של Vertex AI

מפעילים את האינטגרציה של Vertex AI ואת התוספים pgvector במסד הנתונים.

במכונה הווירטואלית של GCE מריצים את הפקודה:

psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE"
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS vector"

הפלט הצפוי בקונסולה:

student@instance-1:~$ psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE"
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS vector"
NOTICE:  extension "google_ml_integration" already exists, skipping
CREATE EXTENSION
CREATE EXTENSION

ייבוא נתונים

מורידים את הנתונים המוכנים ומייבאים אותם למסד הנתונים החדש.

במכונה הווירטואלית של GCE מריצים את הפקודה:

gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_products from stdin csv header"
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_inventory from stdin csv header"
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_stores from stdin csv header"

הפלט הצפוי בקונסולה:

student@instance-1:~$ gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_products from stdin csv header"
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_inventory from stdin csv header" 
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_stores from stdin csv header"
SET
SET
SET
SET
SET
 set_config 
------------
 
(1 row)

SET
SET
SET
SET
SET
SET
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
ALTER SEQUENCE
ALTER TABLE
ALTER TABLE
ALTER TABLE
COPY 941
COPY 263861
COPY 4654

בשלב הבא, מגדירים את הדגלים הנדרשים במסד הנתונים. אפשר להשתמש במסוף האינטרנט ולנהל את הדגלים במופע הראשי, או להשתמש בפקודת gcloud באופן הבא:

export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search
gcloud beta alloydb instances update $ADBCLUSTER-pr \
   --database-flags google_ml_integration.enable_faster_embedding_generation=on,scann.enable_preview_features=on,google_ml_integration.enable_preview_ai_functions=on,google_ml_integration.enable_ai_query_engine=on \
   --region=$REGION \
   --cluster=$ADBCLUSTER \
   --project=$PROJECT_ID \
   --update-mode=FORCE_APPLY

הפלט הצפוי בקונסולה

student@cloudshell:~ (alloydb-hybrid-search)$ export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search
gcloud beta alloydb instances update $ADBCLUSTER-pr \
   --database-flags google_ml_integration.enable_faster_embedding_generation=on,scann.enable_preview_features=on,google_ml_integration.enable_preview_ai_functions=on,google_ml_integration.enable_ai_query_engine=on \
   --region=$REGION \
   --cluster=$ADBCLUSTER \
   --project=$PROJECT_ID \
   --update-mode=FORCE_APPLY
Your active configuration is: [cloudshell-30137]
Operation ID: operation-1784245853151-656c31c44e12b-6084eb8b-d6611419

כדי להפעיל את הדגלים של מסד הנתונים, צריך להפעיל מחדש את המופע. התהליך יימשך כמה דקות. אחרי שהפעולה תושלם, הסטטוס של מופע AlloyDB יהיה 'מוכן'.

7. יצירת הטמעות וקטוריות

אחרי ייבוא הנתונים, יש לנו את הטבלאות הבאות: cymbal_products שבה מאוחסן מידע על מוצרים, cymbal_inventory שבה מתבצע מעקב אחר מלאי הפריטים בכל חנות, ו-cymbal_stores שהיא רשימה של חנויות. כדי לבצע חיפוש סמנטי במוצרים שלנו, אנחנו צריכים ליצור הטבעות וקטוריות של תיאורי המוצרים באמצעות הפונקציה initialize_embeddings. אנחנו נשתמש באינטגרציה של Vertex AI כדי לחשב נתוני וקטורים על סמך תיאורי המוצרים שלנו, ונוסיף אותם לטבלה. במסמכי התיעוד יש מידע נוסף על הטכנולוגיה שבה נעשה שימוש.

כדי להשתמש בשילוב, מתחברים למסד הנתונים באמצעות AlloyDB Studio או באמצעות psql מהמכונה הווירטואלית באמצעות כתובת ה-IP של מכונת AlloyDB והסיסמה של postgres:

psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"

בודקים את הגרסה של התוסף google_ml_integration.

SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';

הגרסה צריכה להיות 1.5.2 ומעלה. דוגמה לפלט:

quickstart_db=> SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';
 extversion 
------------
 1.5.9
(1 row)

גרסת ברירת המחדל צריכה להיות 1.5.2 ומעלה, אבל אם במופע שלכם מופיעה גרסה ישנה יותר, כנראה שצריך לעדכן אותה. בודקים אם התחזוקה הושבתה במופע.

מתקינים את התוסף של הווקטור ויוצרים עמודה חדשה לאחסון ההטמעות ב-cymbal_products

CREATE EXTENSION IF NOT EXISTS vector;
ALTER TABLE cymbal_products ADD COLUMN product_embedding vector(768);

הפלט הצפוי בקונסולה:

quickstart_db=> CREATE EXTENSION IF NOT EXISTS vector;
ALTER TABLE cymbal_products ADD COLUMN product_embedding vector(768);
NOTICE:  extension "vector" already exists, skipping
CREATE EXTENSION
ALTER TABLE

נשתמש ביצירת הטמעה של קבוצות כדי לשפר את היעילות. במדריך אפשר לקרוא מידע נוסף על אפשרויות וטכניקות שונות ליצירת הטמעה. בעבר הפעלנו את הדגל google_ml_integration.enable_faster_embedding_generation שמאפשר לנו ליצור הטמעות בקבוצות.

בנוסף, אנחנו רוצים שההטמעות יתעדכנו כשהערכים בעמודה משתנים, ולכן אנחנו כוללים את הארגומנט incremental_refresh_mode בקריאה לפונקציה. הפעולה הזו מוסיפה עומס למסד הנתונים שלנו, אבל אנחנו מוכנים לשלם את המחיר הזה כדי שההטמעות יסתנכרנו עם התוכן באופן אוטומטי. אם רוצים לעדכן את ההטמעות באופן ידני, אפשר למצוא את ההוראות במסמכי התיעוד.

עכשיו נחבר את הכול וניצור הטמעות. נשתמש בפונקציה initialize_embeddings, נעביר את batch_size של 50 כרמז לגבי גודל האצווה ונגדיר את incremental_refresh_mode ל-transactional

CALL ai.initialize_embeddings(
    model_id => 'text-embedding-005',
    table_name => 'cymbal_products',
    content_column => 'product_description',
    embedding_column => 'product_embedding',
    batch_size => 50,
    incremental_refresh_mode => 'transactional'
);

ועכשיו, אם נוסיף שורה חדשה לטבלה עם הערך NULL בעמודה product_embedding

INSERT INTO "cymbal_products" ("uniq_id", "crawl_timestamp", "product_url", "product_name", "product_description", "list_price", "sale_price", "brand", "item_number", "gtin", "package_size", "category", "postal_code", "available", "product_embedding") VALUES ('fd604542e04b470f9e6348e640cff794', NOW(), 'https://example.com/new_product', 'New Cymbal Product', 'This is a new cymbal product description.', 199.99, 149.99, 'Example Brand', 'EB123', '1234567890', 'Single', 'Cymbals', '12345', TRUE, NULL);

עכשיו, כשנריץ שאילתה על השורה שהוספנו, נראה שהעמודה product_embedding מתעדכנת באופן אוטומטי.

SELECT uniq_id, (product_embedding::real[])[1:5] as product_embedding  FROM cymbal_products WHERE uniq_id='fd604542e04b470f9e6348e640cff794';

הפלט אמור להיראות כך:

quickstart_db=> SELECT uniq_id,(product_embedding::real[])[1:5] as product_embedding  FROM cymbal_products WHERE uniq_id='fd604542e04b470f9e6348e640cff794';
             uniq_id              |                      product_embedding                       
----------------------------------+---------------------------------------------------------------
 fd604542e04b470f9e6348e640cff794 | {0.015003494,-0.005349732,-0.059790313,-0.0087091,-0.0271452}
(1 row)

8. יצירת אינדקס וקטורי

כדי לשפר את הביצועים של חיפוש וקטורי, נוסיף אינדקס ScaNN.

יצירת אינדקס ScaNN

כדי ליצור את אינדקס SCANN, צריך להפעיל עוד תוסף. התוסף alloydb_scann מספק ממשק לעבודה עם אינדקס וקטורי מסוג ANN באמצעות אלגוריתם ScaNN של Google.

CREATE EXTENSION IF NOT EXISTS alloydb_scann;

הפלט אמור להיראות כך:

quickstart_db=> CREATE EXTENSION IF NOT EXISTS alloydb_scann;
CREATE EXTENSION

אפשר ליצור את האינדקס במצב ידני או במצב אוטומטי. המצב 'ידני' מופעל כברירת מחדל, ואפשר ליצור אינדקס ולתחזק אותו כמו כל אינדקס אחר. אבל אם מפעילים את מצב AUTO, אפשר ליצור את האינדקס בלי שיהיה צורך לבצע תחזוקה מצדכם. במסמכי התיעוד אפשר לקרוא בפירוט על כל האפשרויות. במקרה שלנו, אין לנו מספיק שורות כדי ליצור את האינדקס במצב AUTO, ולכן ניצור אותו במצב MANUAL ונכלול פרמטרים של כוונון. במאמרי העזרה מוסבר איך לשנות את הפרמטרים של האינדקס.

CREATE INDEX cymbal_products_embeddings_scann ON cymbal_products
  USING scann (product_embedding cosine)
  WITH (mode='MANUAL', num_leaves=31, max_num_levels = 2);

הפלט אמור להיראות כך:

quickstart_db=> CREATE INDEX cymbal_products_embeddings_scann ON cymbal_products
  USING scann (product_embedding cosine)
  WITH (num_leaves=31, max_num_levels = 2);
CREATE INDEX
quickstart_db=>

בדיקת השימוש באינדקס

עכשיו אפשר להריץ את שאילתת החיפוש הווקטורי במצב EXPLAIN כדי לוודא שהאינדקס נמצא בשימוש.

EXPLAIN (analyze)
WITH trees as (
SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        cp.uniq_id as product_id
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        (cp.product_embedding <=> embedding('text-embedding-005','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;

הפלט הצפוי (הושמטו פרטים לשם הבהרה):

...
Aggregate (cost=16.59..16.60 rows=1 width=32) (actual time=2.875..2.877 rows=1 loops=1)
-> Subquery Scan on trees (cost=8.42..16.59 rows=1 width=142) (actual time=2.860..2.862 rows=1 loops=1)
-> Limit (cost=8.42..16.58 rows=1 width=158) (actual time=2.855..2.856 rows=1 loops=1)
-> Nested Loop (cost=8.42..6489.19 rows=794 width=158) (actual time=2.854..2.855 rows=1 loops=1)
-> Nested Loop (cost=8.13..6466.99 rows=794 width=938) (actual time=2.742..2.743 rows=1 loops=1)
-> Index Scan using cymbal_products_embeddings_scann on cymbal_products cp (cost=7.71..111.99 rows=876 width=934) (actual time=2.724..2.724 rows=1 loops=1)
Order By: (embedding <=> '[0.008864171,0.03693164,-0.024245683,-0.00355923,0.0055611245,0.015985578,...<redacted>...5685,-0.03914233,-0.018452475,0.00826032,-0.07372604]'::vector)
...

מהפלט אפשר לראות בבירור שהשאילתה השתמשה ב-Index Scan באמצעות cymbal_products_embeddings_scann ב-cymbal_products.

9. יצירת מופע של Solr

אנחנו נשתמש ב-Apache Solr עבור החלק של חיפוש הטקסט המלא (FTS) בחיפוש ההיברידי. בשלב הזה תפרסו מכונה וירטואלית עצמאית של Solr במכונה הווירטואלית שיצרתם קודם.

כדי לאבטח את הגישה ל-Solr, נפעיל אימות בסיסי. כדי לעשות את זה, נספק קובץ הגדרות security.json, נטען אותו ונתחיל את קונטיינר Solr docker.

מתחברים למכונה הווירטואלית באמצעות SSH ומתקינים את Docker:

sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

עכשיו אפשר לשנות את פקודת Docker כך שהיא תופעל על ידי המשתמש:

sudo usermod -aG docker $USER
newgrp docker

עכשיו יוצרים את הקובץ security.json כדי להפעיל אימות בסיסי עם שם המשתמש solr והסיסמה SolrRocks.

nano security.json

מעתיקים את ה-JSON הבא לקובץ:

{
  "authentication": {
    "blockUnknown": true,
    "class": "solr.BasicAuthPlugin",
    "credentials": {
      "solr": "IV0EHq1OnNrj6gvRCwvFwTrZ1+z1oBbnQdiVC3otuq0= Ndd7LKvVBAaZIF0QAVi1ekCfAJXr1GGfLtRUXhgrF8c="
    }
  },
  "authorization": {
    "class": "solr.RuleBasedAuthorizationPlugin",
    "permissions": [
      { "name": "security-edit", "role": "admin" }
    ],
    "user-role": { "solr": "admin" }
  }
}

שומרים ויוצאים מ-nano ‏ (Ctrl + O, ‏ Enter, ‏ Ctrl + X).

מפעילים את קונטיינר Solr Docker באמצעות docker run ומעלים את הקובץ security.json לקונטיינר:

docker run -d -p 8983:8983 --name solr --user root -v "$(pwd)/security.json:/var/solr/data/security.json" solr:9 -c -force

מוודאים שהקונטיינר פועל:

docker ps

הפלט אמור להיראות כך:

student@instance-1:~$ docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                         NAMES
90db3c73835e   solr:9    "docker-entrypoint.s..."   7 seconds ago   Up 3 seconds   0.0.0.0:8983->8983/tcp, [::]:8983->8983/tcp   solr

מחכים כמה שניות עד ש-Solr יאתחל, ואז יוצרים אוסף חדש בשם solrindexdemo על ידי שליחת בקשה ל-Solr API עם פרטי האימות הבסיסיים:

curl --user solr:SolrRocks -X POST "http://localhost:8983/solr/admin/collections?action=CREATE&name=solrindexdemo&numShards=1&replicationFactor=1"

הפלט אמור להיראות כך:

student@instance-1:~$ curl --user solr:SolrRocks -X POST "http://localhost:8983/solr/admin/collections?action=CREATE&name=solrindexdemo&numShards=1&replicationFactor=1"
{
  "responseHeader":{
    "status":0,
    "QTime":3586
  },
  "success":{
    "172.17.0.2:8983_solr":{
      "responseHeader":{
        "status":0,
        "QTime":2405
      },
      "core":"solrindexdemo_shard1_replica_n1"
    }
  },
  "warning":"Using _default configset. Data driven schema functionality is enabled by default, which is NOT RECOMMENDED for production use. To turn it off: curl http://{host:port}/solr/solrindexdemo/config -d '{\"set-user-property\": {\"update.autoCreateFields\":\"false\"}}'"

עכשיו נאכלס את מופע Solr בשמות ותיאורים של מוצרים. מעתיקים את קובץ ה-CSV של המוצרים מאחסון בענן אל המכונה הווירטואלית.

gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv .

עכשיו יוצרים סקריפט Python כדי לחלץ את קובץ ה-CSV ולעצב את הנתונים לרשימת JSON לעדכון מספר פריטים בו-זמנית.

nano convert.py

מדביקים את הטקסט הבא בקובץ:

import csv
import json

# Configuration
input_file = 'cymbal_products.csv'
output_file = 'products.json'

def convert():
    try:
        with open(input_file, mode='r', encoding='utf-8') as f_in, \
             open(output_file, mode='w', encoding='utf-8') as f_out:
            
            reader = csv.DictReader(f_in)
            
            products = []
            for row in reader:
                products.append({
                    "id": row['uniq_id'].strip(),
                    "product_name": row['product_name'].strip(),
                    "product_description": row['product_description'].strip()
                })
                
            json.dump(products, f_out, indent=2)
            print(f"Success: Processed {len(products)} products.")
            print(f"Output saved to: {output_file}")

    except Exception as e:
        print(f"An error occurred: {e}")

if __name__ == "__main__":
    convert()

שומרים את הקובץ ומריצים אותו:

python3 convert.py

הפלט אמור להיראות כך:

admin_gopalbhutada_altostrat_com@instance-1:~$ python3 convert.py
Success: Processed 941 products.
Output saved to: products.json

עכשיו שולחים את נתוני ה-JSON אל Apache Solr באמצעות update handler:

curl --user solr:SolrRocks -X POST -H 'Content-Type: application/json' \
  'http://localhost:8983/solr/solrindexdemo/update?commit=true' \
  --data-binary "@products.json"

הפלט אמור להיראות כך:

admin_gopalbhutada_altostrat_com@instance-1:~$ curl --user solr:SolrRocks -X POST -H 'Content-Type: application/json' \
  'http://localhost:8983/solr/solrindexdemo/update?commit=true' \
  --data-binary "@products.json"
{
  "responseHeader":{
    "rf":1,
    "status":0,
    "QTime":3220
  }
}

עכשיו צריך ליצור סוד ב-Secret Manager שיאחסן את פרטי הכניסה של Solr. מכיוון ש-AlloyDB מקשר ל-FDW חיצוני לחיפוש באמצעות ערכי username:password בקידוד base64 לאימות בסיסי, נתחיל בלקיחת המחרוזת בקידוד base64 של solr:SolrRocks:

echo -n "solr:SolrRocks" | base64

פלט:

admin_gopalbhutada_altostrat_com@instance-1:~$ echo -n "solr:SolrRocks" | base64
c29scjpTb2xyUm9ja3M=

יוצרים סוד ב-Google Secret Manager באמצעות פרטי הכניסה האלה בקידוד Base64. ב-Cloud Shell, מריצים את הפקודה הבאה:

echo -n "c29scjpTb2xyUm9ja3M=" | \
gcloud secrets create solr-credentials \
    --replication-policy="automatic" \
    --data-file=-

10. יצירת עטיפת נתונים חיצוניים ב-AlloyDB

משך הצפייה 10:00

כדי לשלוח שאילתות לנתונים שמאוחסנים ב-Apache Solr מ-AlloyDB, צריך ליצור Foreign Data Wrapper ‏ (FDW) עבור Solr וטבלה חיצונית. בעבר אחסנתם את פרטי הכניסה של Solr ב-Secret Manager. כדי ש-AlloyDB יוכל לגשת לסוד, צריך להעניק לחשבון השירות את ההרשאה הנדרשת.

ב-Cloudshell, נותנים לחשבון השירות גישה לסוד solr-credentials:

gcloud secrets add-iam-policy-binding solr-credentials \
    --member="serviceAccount:service-$(gcloud projects describe $(gcloud config get-value project) --format='value(projectNumber)')@gcp-sa-alloydb.iam.gserviceaccount.com" \
    --role="roles/secretmanager.secretAccessor"

הפלט אמור להיראות כך:

admin_@cloudshell:~ (my-project-93954-gke)$ gcloud secrets add-iam-policy-binding solr-credentials \
    --member="serviceAccount:service-$(gcloud projects describe $(gcloud config get-value project) --format='value(projectNumber)')@gcp-sa-alloydb.iam.gserviceaccount.com" \
    --role="roles/secretmanager.secretAccessor"
Your active configuration is: [cloudshell-13031]
Updated IAM policy for secret [solr-credentials].
bindings:
- members:
  - serviceAccount:service-350113473377@gcp-sa-alloydb.iam.gserviceaccount.com
  role: roles/secretmanager.secretAccessor
etag: BwZWyKlkx6Q=
version: 1

מתחברים למסד הנתונים באמצעות AlloyDB Studio (או באמצעות psql כדי להתחבר מהמכונה הווירטואלית). מתחברים אל quickstart_db בתור המשתמש postgres.

מפעילים את תוסף ה-FDW:

CREATE EXTENSION IF NOT EXISTS external_search_fdw;

הפלט אמור להיראות כך:

CREATE EXTENSION

קבלת פרמטרים של חיבור

לפני שמגדירים את שרת הנתונים החיצוני ב-AlloyDB, צריך את כתובת ה-IP הפנימית של המכונה הווירטואלית (שבה פועל Solr) ואת נתיב הסוד.

כדי להדפיס את כתובת ה-IP הפנימית של ה-VM, מריצים את הפקודה הבאה ב-Cloud Shell:

gcloud compute instances describe instance-1 \
    --zone=us-central1-a \
    --format="value(networkInterfaces[0].networkIP)"

הפלט אמור להיראות כך:

10.X.X.X

כדי להדפיס את נתיב המשאב של הסוד ב-Secret Manager, מריצים את הפקודה:

gcloud secrets describe solr-credentials --format="value(name)"

הפלט אמור להיראות כך:

projects/<project_id>/secrets/solr-credentials

כדי להגיע ל-Apache Solr, צריך ליצור שרת נתונים חיצוני. מחליפים את ואת בשאילתה שלמטה בערכים שאחזרתם. כדי לקבל את הגרסה העדכנית ביותר של הסוד, מוסיפים את /versions/latest לנתיב הסודי:

CREATE SERVER solr_demo_server
FOREIGN DATA WRAPPER external_search_fdw
OPTIONS(
    server 'http://<VM_INTERNAL_IP_ADDRESS>:8983',
    search_provider 'solr',
    auth_mode 'secret_manager',
    auth_method 'Basic',
    secret_path '<SECRET_PATH>/versions/latest'
);

הפלט אמור להיראות כך:

CREATE SERVER

בשלב הבא, מגדירים את הטבלה החיצונית. אחרי המטא-נתונים, צריך לספק את הגדרת סכימת השדות של Solr כדי להתאים לנתונים שנפרסו קודם. בטבלה המרוחקת מציינים את השם של אוסף Solr.

CREATE FOREIGN TABLE solrindexdemo (
    metadata external_search_fdw_schema.OpaqueMetadata,
    id TEXT,
    product_name TEXT,
    product_description TEXT
)
SERVER solr_demo_server
OPTIONS(
    remote_table_name 'solrindexdemo'
);

יוצרים מיפוי משתמשים לשרת:

CREATE USER MAPPING FOR CURRENT_USER SERVER solr_demo_server;

עכשיו אפשר לבדוק את הטבלה החיצונית:

SELECT id, product_name
FROM solrindexdemo
ORDER BY metadata <@> 'product_description:cherry' DESC
limit 10;

הפלט אמור להיראות כך:

"id","product_name"
"d536e9e823296a2eba198e52dd23e712","Cherry Tree"
"390cf08feac229e7b752709fd1f943b3","Woven Round Placemat, Set of Twelve, Grass"
"2c9aa7ac98c30abf78dd9c62a68a34e6","48 Scented Wax Melts Wax Cubes: Jelly Belly Jelly Beans Candy Bulk Soy Wax Melts For Candle Warmer, Wax Warmers, Wax Melt Warmers In 8 Pack Set"

11. שימוש בחיפוש היברידי

משך הצפייה 10:00

עכשיו, אחרי שהכול מוגדר, אפשר להשתמש בפונקציה ai.hybrid_search() כדי לשלב בין חיפוש וקטורי לחיפוש טקסט מלא. מידע נוסף על חיפוש היברידי מופיע במאמרי העזרה. כשמשתמשים בחיפוש היברידי, כברירת מחדל, תוצאות השאילתה משתמשות באלגוריתם Reciprocal Rank Fusion כדי לדרג את התוצאות מכמה שאילתות. קודם ננסה חיפוש וקטורי וחיפוש היברידי בנפרד כדי לנתח את ההבדלים ביניהם.

השאילתה הבאה מבצעת חיפוש וקטורי כדי למצוא מוצרים שדומים למוצר cherry. המערך מספק רשימה של חיפושים לביצוע. במקרה הזה, אנחנו משתמשים רק בחיפוש וקטורי, אבל בהמשך נספק גם חיפוש וקטורי וגם חיפוש טקסט מלא.

SELECT id, score, cymbal_products.product_name, cymbal_products.product_description
FROM ai.hybrid_search(
  ARRAY[
      '{
        "data_type": "vector",
        "table_name": "cymbal_products",
        "key_column": "uniq_id",
        "vec_column": "product_embedding",
        "distance_operator": "public.<=>",
        "limit": 3,
        "query_vector": "ai.embedding(''text-embedding-005'', ''cherry'')::vector"
      }'::JSONB
  ]
) JOIN cymbal_products ON id = cymbal_products.uniq_id;

בפלט, עץ דובדבן הוא התוצאה הראשונה, אבל שימו לב ששתי התוצאות הבאות הן גם עצי פרי. הסיבה לכך היא שכשאנחנו משתמשים בחיפוש וקטורי בעמודה product_description, אנחנו מוצאים התאמות סמנטיות לתנאי החיפוש שלנו.

"id","score","product_name","product_description"
"d536e9e823296a2eba198e52dd23e712","0.01639344262295082","Cherry Tree","This is a beautiful cherry tree that will produce delicious cherries. It is an deciduous tree that grows to be about 15 feet tall. The leaves are dark green in the summer and turn a beautiful red in the fall. Cherry trees are known for their beauty and their ability to provide shade and privacy. Cherry trees prefer a cool, moist climate and sandy soil. They are best suited for USDA zones 4-9."
"b70c44b1a38c0a2329fa583c9109a80f","0.016129032258064516","Peach Tree","This is a beautiful peach tree that will produce delicious peaches. It is an evergreen tree that grows to be about 20 feet tall. The leaves are dark green in the summer and turn a beautiful yellow in the fall. Peach trees are known for their beauty and their ability to provide shade and privacy. Peach trees prefer a cool, moist climate and sandy soil. They are best suited for USDA zones 2-9."
"23e41a71d63d8bbc9bdfa1d118cfddc5","0.015873015873015872","Apple Tree","This is a beautiful apple tree that will produce delicious apples. It is a deciduous tree that grows to be about 30 feet tall. The leaves are dark green in the summer and turn a beautiful red, orange, and yellow in the fall. Apple trees are known for their strength and durability. They are also a popular choice for shade trees. Apple trees prefer a cool, moist climate and loamy soil. They are best suited for USDA zones 4-8."

כדי לבצע חיפוש טקסט מלא באמצעות Apache Solr FDW, מריצים את השאילתה הבאה:

SELECT id, score, cymbal_products.product_name, cymbal_products.product_description
FROM ai.hybrid_search(
  ARRAY[
      '{
        "limit": 3,
        "data_type": "external_search_fdw",
        "table_name": "solrindexdemo",
        "key_column": "id",
        "query_text_input": "product_description:cherry"
      }'::JSONB
  ]
) JOIN cymbal_products ON id = cymbal_products.uniq_id;

שימו לב: בתוצאות, מאחר שחיפוש הטקסט המלא מתבסס על התאמת טוקנים, מוצגות כל התוצאות שמכילות את המילה cherry בתיאור המוצר.

"id","score","product_name","product_description"
"d536e9e823296a2eba198e52dd23e712","0.01639344262295082","Cherry Tree","This is a beautiful cherry tree that will produce delicious cherries. It is an deciduous tree that grows to be about 15 feet tall. The leaves are dark green in the summer and turn a beautiful red in the fall. Cherry trees are known for their beauty and their ability to provide shade and privacy. Cherry trees prefer a cool, moist climate and sandy soil. They are best suited for USDA zones 4-9."
"390cf08feac229e7b752709fd1f943b3","0.016129032258064516","Woven Round Placemat, Set of Twelve, Grass","...These placemats are great for special occasions and holidays, but are also perfect to accessorize your everyday place settings.|Measurements. 15-inch round diameter is the perfect size for most table sizes and shapes.|Pop Colors. Choose from 7 pop woven color placemats including: Black, Cherry, Grass, Taupe, Navy, Sun and Graphite."
"2c9aa7ac98c30abf78dd9c62a68a34e6","0.015873015873015872","48 Scented Wax Melts Wax Cubes: Jelly Belly Jelly Beans Candy Bulk Soy Wax Melts For Candle Warmer, Wax Warmers, Wax Melt Warmers In 8 Pack Set","...From These Flavors: Lemon Drop, Mixed Berry Smoothie, Sizzling Cinnamon, Crushed Pineapple, Juicy Pear, Cotton Candy, Toasted Marshmallow, French Vanilla, Watermelon, Red Apple, Very Cherry, Buttered Popcorn..."

עכשיו אפשר לשלב בין חיפוש סמנטי לבין חיפוש טקסט מלא כדי לקבל תוצאות משמעותיות יותר. נניח שאנחנו רוצים לחפש עץ שיכול לגדול לגובה שגדול יותר מגובה של בית, ושמקורו בקליפורניה. פיצלנו את השאילתה כדי להשתמש בהבנה סמנטית של הכוונה לעומת התאמה מילולית. החיפוש הווקטורי מטפל בחלק התיאורי: "עץ שיכול לגדול לגובה יותר גדול מבית", כי הוא מבין את הרעיון של קנה מידה בלי צורך במילות מפתח מדויקות. בינתיים, החיפוש בטקסט המלא מטפל במונח 'קליפורניה' כמסנן קפדני כדי לוודא שנקבל התאמה גיאוגרפית מדויקת ולא רק משהו דומה מבחינה מושגית.

SELECT id, score, cymbal_products.product_name, cymbal_products.product_description
FROM ai.hybrid_search(
  ARRAY[
    '{
        "data_type": "vector",
        "table_name": "cymbal_products",
        "key_column": "uniq_id",
        "vec_column": "product_embedding",
        "distance_operator": "public.<=>",
        "limit": 3,
        "query_vector": "ai.embedding(''text-embedding-005'', ''tree that can grow taller than a house'')::vector"
      }'::JSONB,
      '{
        "limit": 3,
        "data_type": "external_search_fdw",
        "table_name": "solrindexdemo",
        "key_column": "id",
        "query_text_input": "product_description:California"
      }'::JSONB
  ]
) JOIN cymbal_products ON id = cymbal_products.uniq_id;

התוצאות הצפויות:

"id","score","product_name","product_description"
"a589fd36a8a20fd9472d2403d6ed692a","0.00819672631147241","California Redwood","This is a beautiful redwood tree that can grow to be over 300 feet tall. It is an evergreen tree that grows in the coastal forests of California. Redwoods are known for their beauty and their strength. They are best suited for USDA zones 7-10."
"ef9432802da24041594c2cf368dfb4d2","0.008064521129029258","Madrone","This is a beautiful madrona tree that can grow to be over 80 feet tall. It is an evergreen tree that grows in the coastal forests of California. Madronas are known for their beauty and their bark. They are best suited for USDA zones 7-10."
"1360d8642bc218e4ea28e9c32b2e1721","0.007936512936504936","California Sycamore","This is a beautiful sycamore tree that can grow to be over 100 feet tall. It is an deciduous tree that grows in the valleys and foothills of California. California sycamores are known for their beauty and their shade. They are best suited for USDA zones 7-10."

12. ניקוי הסביבה

בסיום שיעור ה-Lab, משמידים את המופעים ואת האשכול של AlloyDB.

מחיקת אשכול AlloyDB וכל המכונות

אם השתמשתם בגרסת הניסיון של AlloyDB. אל תמחקו את אשכול הניסיון אם אתם מתכננים לבדוק מעבדות ומשאבים אחרים באמצעות אשכול הניסיון. לא תוכלו ליצור אשכול ניסיון נוסף באותו פרויקט.

האשכול נהרס עם האפשרות force, שמוחקת גם את כל המופעים ששייכים לאשכול.

ב-Cloud Shell, מגדירים את משתני הפרויקט והסביבה אם התנתקתם וכל ההגדרות הקודמות אבדו:

gcloud config set project <your project id>
export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search
export PROJECT_ID=$(gcloud config get-value project)

מחיקת האשכול:

gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force

הפלט הצפוי בקונסולה:

admin_@cloudshell:~ (my-project-93954-gke)$ gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force
All of the cluster data will be lost when the cluster is deleted.

Do you want to continue (Y/n)?  Y

Operation ID: operation-1784270790060-656c8ea9fea06-1b93001f-846543e0
Deleting cluster...done.   

מחיקת גיבויים של AlloyDB

מחיקת כל הגיבויים של AlloyDB באשכול:

for i in $(gcloud alloydb backups list --filter="CLUSTER_NAME: projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER" --format="value(name)" --sort-by=~createTime) ; do gcloud alloydb backups delete $(basename $i) --region $REGION --quiet; done

הפלט הצפוי בקונסולה:

admin_@cloudshell:~ (my-project-93954-gke)$ for i in $(gcloud alloydb backups list --filter="CLUSTER_NAME: projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER" --format="value(name)" --sort-by=~createTime) ; do gcloud alloydb backups delete $(basename $i) --region $REGION --quiet; done
Operation ID: operation-1784271231983-656c904f71e05-1389a145-f101ceee
Deleting backup...done.

עכשיו אפשר להשמיד את המכונה הווירטואלית

מחיקת מכונה וירטואלית ב-GCE

ב-Cloud Shell, מריצים את הפקודה:

export GCEVM=instance-1
export ZONE=us-central1-a
gcloud compute instances delete $GCEVM \
    --zone=$ZONE \
    --quiet

הפלט הצפוי בקונסולה:

admin_@cloudshell:~ (my-project-93954-gke)$ export GCEVM=instance-1
export ZONE=us-central1-a
gcloud compute instances delete $GCEVM \
    --zone=$ZONE \
    --quiet
Deleted

13. מזל טוב

כל הכבוד, סיימתם את ה-Codelab!

מה נכלל

  • איך פורסים אשכול AlloyDB ומכונה ראשית
  • איך מתחברים ל-AlloyDB ממכונה וירטואלית של Google Compute Engine
  • איך יוצרים מסד נתונים ומפעילים את AlloyDB AI
  • איך טוענים נתונים למסד הנתונים
  • איך משתמשים ב-AlloyDB Studio
  • יצירת הטמעות באמצעות Vertex AI
  • איך יוצרים אינדקס וקטורי של ScaNN כדי לשפר את החיפוש הווקטורי
  • איך יוצרים Foreign Data Wrapper ‏ (FDW) ל-Apache Solr
  • ביצוע חיפוש היברידי על ידי שילוב של חיפוש סמנטי ב-AlloyDB עם חיפוש טקסט מלא ב-Solr.

השלבים הבאים

אפשר לעיין ב-Codelabs נוספים של AlloyDB באתר הרשמי של Codelab.