בדף הזה מתוארת הפונקציה SEARCH והיכולות המתקדמות השונות שלה, שמשמשות לביצוע שאילתות של חיפוש טקסט מלא בטבלאות של Spanner.
שאילתה של אינדקס חיפוש
Spanner מספק את הפונקציה SEARCH לשימוש בשאילתות של אינדקס חיפוש. תרחיש שימוש לדוגמה הוא אפליקציה שבה המשתמשים מזינים טקסט בתיבת חיפוש, והאפליקציה שולחת את קלט של משתמשים ישירות אל הפונקציה SEARCH. הפונקציה SEARCH תשתמש באינדקס חיפוש כדי למצוא את הטקסט הזה.
הפונקציה SEARCH דורשת שני ארגומנטים:
- שם של אינדקס חיפוש
- שאילתת חיפוש
הפונקציה SEARCH פועלת רק כשמוגדר אינדקס חיפוש. אפשר לשלב את הפונקציה SEARCH עם כל מבנה SQL שרירותי, כמו מסננים, צבירות או שאילתות איחוד (join).
אי אפשר להשתמש בפונקציה SEARCH בשאילתות של טרנזקציות.
השאילתה הבאה משתמשת בפונקציה SEARCH כדי להחזיר את כל האלבומים שכוללים את friday או monday בשם:
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'friday OR monday')
PostgreSQL
בדוגמה הזו נעשה שימוש ב-spanner.search.
SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'friday OR monday')
שאילתת חיפוש
שאילתות החיפוש משתמשות בתחביר של שאילתת החיפוש הגולמית כברירת מחדל. אפשר לציין תחבירים חלופיים באמצעות הארגומנט SEARCH
dialect.
ניב rquery
ניב ברירת המחדל הוא שאילתת חיפוש גולמית. Spanner משתמש בשפה ספציפית לדומיין (DSL) שנקראת rquery.
השפה של שאילתת החיפוש פועלת לפי אותם כללים כמו מפצל המילים של טקסט רגיל כשמפצלים את שאילתת החיפוש לקלט למונחים נפרדים. זה כולל פילוח של שפות אסייתיות.
מידע על השימוש ב-rquery זמין במאמר בנושא תחביר rquery.
מילים דיאלקט
השפה dialect דומה ל-rquery, אבל פשוטה יותר. היא לא משתמשת באופרטורים מיוחדים. לדוגמה, OR נחשב למונח חיפוש ולא לאופרטור של איחוד. המירכאות הכפולות מטופלות כסימני פיסוק ולא כחיפוש של צירוף מילים, והן מתעלמות מהן.
כשמשתמשים במילה dialect, AND מוחל באופן מרומז על כל המונחים, והוא נדרש במהלך ההתאמה. הוא פועל לפי אותם כללים כמו טוקנייזר של טקסט רגיל
כשמפצלים את שאילתת החיפוש לקטעי טקסט.
מידע על השימוש במילה dialect מופיע במאמר בנושא תחביר של מילים.
words_phrase dialect
בניב words_phrase לא משתמשים באופרטורים מיוחדים, וכל המונחים נחשבים לביטוי. כלומר, המונחים צריכים להיות סמוכים זה לזה ובסדר שצוין.
בדומה ל-rquery, הניב words_phrase פועל לפי אותם כללים כמו מנתח הטוקנים של טקסט פשוט כשמפצלים את שאילתת החיפוש של הקלט למונחים.
מידע על שימוש בניב words_phrase זמין במאמר תחביר של words phrase.
הרחבת שאילתות החיפוש כדי להגדיל את מספר התוצאות שקשורות אליהן
כדי להגדיל את הסיכוי למצוא תוצאות רלוונטיות, אפשר להשתמש ביכולות המתקדמות של Spanner להרחבת שאילתות חיפוש באמצעות מונחים קשורים, מילים נרדפות ותיקוני איות. היכולות האלה כוללות:
מידע נוסף זמין במאמר בנושא חיפוש עם שיפור שאילתות.
דרישות לגבי שאילתות SQL
כדי להשתמש באינדקס חיפוש, שאילתת SQL צריכה לעמוד בכמה תנאים. אם התנאים האלה לא מתקיימים, השאילתה משתמשת בתוכנית שאילתה חלופית או נכשלת אם לא קיימת תוכנית חלופית.
השאילתות צריכות לעמוד בתנאים הבאים:
הפונקציות SEARCH ו-
SEARCH_SUBSTRINGדורשות אינדקס חיפוש. Spanner לא תומך בפונקציות האלה בשאילתות שמופעלות מול טבלת הבסיס או אינדקסים משניים.אינדקסים עם חלוקה למחיצות צריכים לכלול את כל עמודות החלוקה למחיצות שמוגדרות על ידי תנאי שוויון בסעיף
WHEREשל השאילתה.לדוגמה, אם אינדקס החיפוש מוגדר כ-
PARTITION BY x, y, השאילתה חייבת לכלול צירוף בפסוקיתWHEREשלx = <parameter or constant> AND y = <parameter or constant>. אם התנאי הזה לא קיים, האופטימיזציה של השאילתה לא מתבצעת על אינדקס החיפוש הזה.כל העמודות
TOKENLISTשאליהן מתייחסים האופרטוריםSEARCHו-SEARCH_SUBSTRINGחייבות להיות באינדקס באותו אינדקס חיפוש.לדוגמה, נניח שיש לכם את הטבלה הבאה ואת הגדרת האינדקס:
GoogleSQL
CREATE TABLE Albums ( AlbumId STRING(MAX) NOT NULL, AlbumTitle STRING(MAX), AlbumStudio STRING(MAX), AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN, AlbumStudio_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumStudio)) HIDDEN ) PRIMARY KEY(AlbumId); CREATE SEARCH INDEX AlbumsTitleIndex ON Albums(AlbumTitle_Tokens); CREATE SEARCH INDEX AlbumsStudioIndex ON Albums(AlbumStudio_Tokens);PostgreSQL
CREATE TABLE albums ( albumid character varying NOT NULL, albumtitle character varying, albumstudio character varying, albumtitle_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle)) VIRTUAL HIDDEN, albumstudio_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumstudio)) VIRTUAL HIDDEN, PRIMARY KEY(albumid)); CREATE SEARCH INDEX albumstitleindex ON albums(albumtitle_tokens); CREATE SEARCH INDEX albumsstudioindex ON albums(albumstudio_tokens);השאילתה הבאה נכשלת כי אין אינדקס חיפוש יחיד שמכיל את
AlbumTitle_Tokensוגם אתAlbumStudio_Tokens:GoogleSQL
SELECT AlbumId FROM Albums WHERE SEARCH(AlbumTitle_Tokens, @p1) AND SEARCH(AlbumStudio_Tokens, @p2)PostgreSQL
בדוגמה הזו נעשה שימוש בפרמטרים של השאילתה
$1ו-$2שמשויכים לערכים 'fast car' ו-'blue note', בהתאמה.SELECT albumid FROM albums WHERE spanner.search(albumtitle_tokens, $1) AND spanner.search(albumstudio_tokens, $2)אם העמודה של סדר המיון מאפשרת ערך NULL, גם הסכימה וגם השאילתה צריכות להחריג שורות שבהן העמודה של סדר המיון היא NULL. פרטים נוספים זמינים במאמר בנושא סדר המיון של אינדקס החיפוש.
אם אינדקס החיפוש מסונן לפי NULL, השאילתה חייבת לכלול את אותו ביטוי סינון לפי NULL שמשמש באינדקס. פרטים נוספים זמינים במאמר בנושא אינדקסים של חיפושים עם סינון NULL.
Search indexes וsearch functions לא נתמכים ב-DML, ב-partitioned DML או בשאילתות מחולקות.
אינדקסים של חיפוש ופונקציות חיפוש משמשים בדרך כלל בטרנזקציות לקריאה בלבד. אם הדרישות של האפליקציה מאפשרות תוצאות לא עדכניות, יכול להיות שתוכלו לשפר את זמן האחזור על ידי הפעלת שאילתות חיפוש עם משך זמן של 10 שניות או יותר. מידע נוסף מופיע במאמר קריאת נתונים לא עדכניים. האפשרות הזו שימושית במיוחד לשאילתות חיפוש שמתפצלות להרבה חלקי אינדקס.
לא מומלץ להשתמש באינדקסים של חיפוש ובפונקציות חיפוש בעסקאות של קריאה וכתיבה.
במהלך ההפעלה, שאילתות חיפוש נועלות מחיצה שלמה של אינדקס. כתוצאה מכך, שיעור גבוה של שאילתות חיפוש בעסקאות קריאה-כתיבה עלול לגרום להתנגשויות נעילה שיובילו לעליות פתאומיות בזמן האחזור. כברירת מחדל, אינדקסים של חיפוש לא נבחרים אוטומטית בעסקאות של קריאה וכתיבה. אם שאילתה נאלצת להשתמש באינדקס חיפוש בעסקת קריאה-כתיבה, היא נכשלת כברירת מחדל. החיפוש ייכשל גם אם השאילתה מכילה אחת מפונקציות החיפוש. אפשר לבטל את ההתנהגות הזו באמצעות רמז ברמת ההצהרה של GoogleSQL @{ALLOW_SEARCH_INDEXES_IN_TRANSACTION=TRUE} (אבל עדיין יש סיכון להתנגשויות נעילה בשאילתות).
אחרי שהתנאים לשימוש באינדקס מתקיימים, הכלי לאופטימיזציה של שאילתות מנסה להאיץ תנאים של שאילתות שאינן טקסטואליות (כמו Rating > 4). אם אינדקס החיפוש לא כולל את העמודה המתאימה TOKENLIST, התנאי לא מואץ והוא נשאר תנאי שיורי.
פרמטרים של שאילתה
הארגומנטים של שאילתת החיפוש מצוינים כמחרוזת מילולית או כפרמטר של שאילתה. מומלץ להשתמש בפרמטרים של שאילתה לחיפוש טקסט מלא במקום במחרוזות מילוליות, כשארגומנטים מאפשרים ערך פרמטר.
בחירת אינדקס
בדרך כלל, Spanner בוחר את האינדקס הכי יעיל לשאילתה באמצעות מודלים מבוססי-עלות. עם זאת, הרמז FORCE_INDEX מורה במפורש ל-Spanner להשתמש באינדקס חיפוש ספציפי. לדוגמה, הקטע הבא מראה איך לכפות על Spanner להשתמש ב-AlbumsIndex:
GoogleSQL
SELECT AlbumId
FROM Albums @{FORCE_INDEX=AlbumsIndex}
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")
PostgreSQL
SELECT albumid
FROM albums/*@force_index=albumsindex*/
WHERE spanner.search(albumtitle_tokens, 'fifth symphony')
אם אינדקס החיפוש שצוין לא עומד בדרישות, השאילתה תיכשל, גם אם יש אינדקסים אחרים שעומדים בדרישות.
תקצירים בתוצאות החיפוש
קטע טקסט הוא חלק ממחרוזת נתונה שנותן למשתמשים מושג לגבי התוכן של תוצאת חיפוש, והסיבה לכך שהתוצאה רלוונטית לשאילתה שלהם.
לדוגמה, Gmail משתמש בתקצירים כדי לציין את החלק באימייל שתואם לשאילתת החיפוש:

יש כמה יתרונות ליצירת קטע קוד על ידי מסד הנתונים:
- נוחות: לא צריך להטמיע לוגיקה כדי ליצור תקצירים משאילתת חיפוש.
- יעילות: קטעי קוד מקטינים את גודל הפלט מהשרת.
הפונקציה SNIPPET
יוצרת את הקטע. הפונקציה מחזירה את החלק הרלוונטי של ערך המחרוזת המקורי, יחד עם מיקומי התווים להדגשה. לאחר מכן הלקוח יכול לבחור איך להציג את קטע הקוד למשתמש הקצה (לדוגמה, באמצעות טקסט מודגש או מודגש).
לדוגמה, הפקודה הבאה משתמשת ב-SNIPPET כדי לאחזר טקסט מ-AlbumTitle:
GoogleSQL
SELECT AlbumId, SNIPPET(AlbumTitle, "Fast Car")
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "Fast Car")
PostgreSQL
בדוגמה הזו נעשה שימוש ב-spanner.snippet.
SELECT albumid, spanner.snippet(albumtitle, 'Fast Car')
FROM albums
WHERE spanner.search(albumtitle_tokens, 'Fast Car')
המאמרים הבאים
- איך לדרג את תוצאות החיפוש
- איך מבצעים חיפוש של מחרוזת משנה
- איך מחלקים את תוצאות החיפוש לדפים
- איך משלבים שאילתות של טקסט מלא עם שאילתות שאינן טקסט
- איך מחפשים בכמה עמודות