בדף הזה מוסבר איך להוסיף טוקניזציה לטבלאות. הטוקניזציה נחוצה כדי ליצור את האסימונים שמשמשים באינדקס החיפוש.
טוקניזציה היא תהליך של המרת ערכים לטוקנים. השיטה שבה משתמשים כדי ליצור טוקנים ממסמך קובעת את הסוגים והיעילות של החיפושים שהמשתמשים יכולים לבצע בו.
Spanner מספק tokenizers לטקסט בשפה טבעית, למחרוזות משנה, לטקסט מילולי, למספרים ולערכים בוליאניים. סכימת מסד הנתונים משתמשת בטוקנייזר שתואם לסוג החיפוש שנדרש לעמודה. אלה המאפיינים של טוקנייזרים:
- כל טוקנייזר הוא פונקציית SQL שמקבלת קלט, כמו מחרוזת או מספר, וארגומנטים בעלי שם לאפשרויות נוספות.
- הפלט של הטוקנייזר הוא
TOKENLIST.
לדוגמה, מחרוזת הטקסט The quick brown fox jumps over the lazy dog
מפולחת לטוקנים כך: [the,quick,brown,fox,jumps,over,the,lazy,dog].
מחרוזת HTML The <b>apple</b> is <i>red</i> עוברת טוקניזציה ל-[the,apple,is,red].
לאסימונים יש את המאפיינים הבאים:
- האסימונים מאוחסנים בעמודות שמשתמשות בסוג הנתונים
TOKENLIST. - כל אסימון מאוחסן כרצף של בייטים, עם קבוצה אופציונלית של מאפיינים משויכים. לדוגמה, באפליקציות של חיפוש טקסט מלא, אסימון הוא בדרך כלל מילה אחת ממסמך טקסטואלי.
- כשמבצעים טוקניזציה של ערכי HTML, Spanner יוצר מאפיינים שמציינים את מידת הבולטות של טוקן במסמך. מערכת Spanner משתמשת במאפיינים האלה כדי להקצות ניקוד, וכך להדגיש מונחים בולטים יותר (כמו כותרת).
יצירת טוקנים
Spanner תומך בפונקציות הבאות של טוקנייזר:
מפצל מילים לטוקנים לחיפוש טקסט מלא (
TOKENIZE_FULLTEXT) יוצר טוקנים של מילים שלמות לשאילתות בשפה טבעית.דוגמה
שתי הפונקציות הבאות
GoogleSQL
TOKENIZE_FULLTEXT("Yellow apple") TOKENIZE_FULLTEXT("Yellow <b>apple</b>", content_type=>"text/html")PostgreSQL
בדוגמה הזו נעשה שימוש ב-
spanner.tokenize_fulltext.spanner.tokenize_fulltext("Yellow apple") spanner.tokenize_fulltext('Yellow <b>apple</b>', context_type=>'text/html')יפיקו את אותם טוקנים:
[yellow,apple].Substring tokenizer (
TOKENIZE_SUBSTRING) יוצר טוקנים לכל n-gram של כל מילה. הוא משמש לחיפוש מחרוזות משנה של מילים בטקסט.דוגמה
GoogleSQL
TOKENIZE_SUBSTRING('hello world', ngram_size_min=>4, ngram_size_max=>6)PostgreSQL
בדוגמה הזו נעשה שימוש ב-
spanner.tokenize_substring.spanner.tokenize_substring('hello world', ngram_size_min=>4, ngram_size_max=>6)הפלט הוא הטוקנים הבאים:
[ello,hell,hello,orld,worl,world].N-gram tokenizer (
TOKENIZE_NGRAMS) יוצר n-grams מקלט (בלי לפצל אותו למילים נפרדות). הוא משמש להאצת פרדיקטים של ביטויים רגולריים.דוגמה
הפונקציה הבאה:
GoogleSQL
TOKENIZE_NGRAMS("Big Time", ngram_size_min=>4, ngram_size_max=>4)PostgreSQL
בדוגמה הזו נשתמש ב-
spanner.tokenize_ngrams.spanner.tokenize_ngrams('big time', ngram_size_min=>4, ngram_size_max=>4)הפלט הוא הטוקנים הבאים:
["Big ","ig T","g Ti"," Tim", "Time"].אמצעי טוקניזציה של התאמה מדויקת (
TOKENו-TOKENIZE_BOOL) משמשים לחיפוש שורות שמכילות ערך מסוים באחת מהעמודות שלהן. לדוגמה, אפליקציה שמבצעת אינדוקס של קטלוג מוצרים עשויה לרצות לחפש מוצרים של מותג מסוים ובצבע מסוים.דוגמאות
הפונקציות הבאות:
GoogleSQL
TOKEN("hello") TOKEN(["hello", "world"])PostgreSQL
בדוגמה הזו נעשה שימוש ב-
spanner.token.spanner.token('hello')הפלט הוא הטוקנים הבאים:
[hello].הפונקציה הבאה:
GoogleSQL
TOKENIZE_BOOL(true)PostgreSQL
בדוגמה הזו נעשה שימוש ב-
spanner.tokenize_bool.spanner.tokenize_bool(true)הטוקן שנוצר:
[y].מספרי טוקנים (
TOKENIZE_NUMBER) משמשים ליצירת קבוצה של טוקנים שמאיצים חיפושים של השוואות מספריות. במקרים של תנאי שוויון, הטוקן הוא המספר עצמו. במקרים של תנאי טווח (כמוrating >= 3.5), קבוצת האסימונים מורכבת יותר.דוגמאות
הצהרות הפונקציה הבאות:
GoogleSQL
TOKENIZE_NUMBER(42, comparison_type=>'equality') TOKENIZE_NUMBER(42, comparison_type=>'all', granularity=>10, min=>1, max=>100)PostgreSQL
בדוגמה הזו נעשה שימוש ב-
spanner.tokenize_number.spanner.tokenize_number(42, comparison_type=>'equality') spanner.tokenize_number(42, comparison_type=>'all', granularity=>10, min=>1, max=>100)הפלט של הפקודות יהיה הטוקנים הבאים, בהתאמה:
"==42"ו-"==42","[1,75]","[36, 45]","[36,55]","[36, 75]".אסימונים של JSON ו-JSONB (
TOKENIZE_JSONו-TOKENIZE_JSONB) משמשים ליצירת קבוצה של אסימונים שמאיצים את ההכלה של JSON ואת פרדיקטים של קיום מפתח, כמוdoc[@key] IS NOT NULL(GoogleSQL) אוdoc ? 'key'(PostgreSQL).
בדרך כלל משתמשים בפונקציות של טוקניזציה בביטוי של עמודה שנוצרה. הגדרנו את העמודות האלה כ-HIDDEN כדי שהן לא ייכללו בתוצאות של שאילתות SELECT *.
בדוגמה הבאה נעשה שימוש ב-tokenizer של טקסט מלא וב-tokenizer של נתונים מספריים כדי ליצור מסד נתונים שמאחסן שמות ודירוגים של אלבומי מוזיקה. הצהרת ה-DDL מבצעת שני דברים:
- הגדרת עמודות הנתונים
AlbumTitleו-Rating. הגדרות של
AlbumTitle_TokensושלAlbumRating_Tokens. העמודות האלהTOKENLISTמבצעות טוקניזציה של הערכים בעמודות הנתונים כדי ש-Spanner יוכל ליצור להם אינדקס.GoogleSQL
CREATE TABLE Albums ( AlbumId STRING(MAX) NOT NULL, AlbumTitle STRING(MAX), Rating FLOAT64, AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN, Rating_Tokens TOKENLIST AS (TOKENIZE_NUMBER(Rating)) HIDDEN ) PRIMARY KEY(AlbumId);PostgreSQL
CREATE TABLE albums ( albumid character varying NOT NULL, albumtitle character varying, albumtitle_Tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle)) VIRTUAL HIDDEN, PRIMARY KEY(albumid));
בכל פעם שמשנים את ערכי הבסיס, הערכים AlbumTitle_Tokens ו-Rating_Tokens מתעדכנים אוטומטית.
יצירת טוקנים מטקסט פשוט או מתוכן HTML
הטוקניזציה של טקסט תומכת בסוגי תוכן של טקסט פשוט ו-HTML. כדי ליצור אסימונים, משתמשים בפונקציה TOKENIZE_FULLTEXT של Spanner. לאחר מכן משתמשים בהצהרת ה-DDL CREATE SEARCH INDEX כדי ליצור את אינדקס החיפוש.
לדוגמה, משתמשים בהצהרת ה-DDL CREATE TABLE הבאה כדי ליצור טוקנים מ-AlbumTitles בטבלה Albums באמצעות הפונקציה TOKENIZE_FULLTEXT. הצהרת ה-DDL CREATE SEARCH INDEX יוצרת אינדקס חיפוש עם AlbumTitles_Tokens חדש.
GoogleSQL
CREATE TABLE Albums (
AlbumId STRING(MAX) NOT NULL,
AlbumTitle STRING(MAX),
AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN
) PRIMARY KEY(AlbumId);
CREATE SEARCH INDEX AlbumsIndex ON Albums(AlbumTitle_Tokens)
PostgreSQL
CREATE TABLE albums (
albumid character varying NOT NULL,
albumtitle character varying,
albumtitle_tokens spanner.tokenlist
GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle)) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));
CREATE SEARCH INDEX albumsindex ON albums(albumtitle_tokens)
תהליך הטוקניזציה מתבצע לפי הכללים הבאים:
- תהליך הטוקניזציה לא כולל הסרת תחיליות וסיומות או תיקון של מילים שאויתו בצורה שגויה. לדוגמה, במשפט 'חתול הסתכל על קבוצת חתולים', האסימון 'חתול' מאונדקס בנפרד מהאסימון 'חתולים'. בהשוואה למנועי חיפוש אחרים שמבצעים נרמול של טוקנים במהלך כתיבה, Spanner מספק אפשרות להרחיב את שאילתת החיפוש כך שתכלול צורות שונות של מילים. מידע נוסף זמין במאמר בנושא מצב שאילתה משופר.
- מילות עצירה (כמו 'a') נכללות באינדקס החיפוש.
- חיפוש טקסט מלא תמיד לא תלוי באותיות רישיות. תהליך הטוקניזציה ממיר את כל הטוקנים לאותיות קטנות.
במהלך תהליך הטוקניזציה, המיקומים של כל טוקן בטקסט המקורי נשמרים. המיקומים האלה משמשים בהמשך להתאמת ביטויים. המיקומים נשמרים באינדקס החיפוש לצד מספרי המסמכים.
Google ממשיכה לשפר את האלגוריתמים של הטוקניזציה. במקרים מסוימים, יכול להיות שבעתיד מחרוזת תעבור טוקניזציה באופן שונה מהאופן שבו היא עוברת טוקניזציה עכשיו. אנחנו מקווים שמקרים כאלה יהיו נדירים ביותר. דוגמה לכך היא שיפור בפילוח של שפות סיניות, יפניות וקוריאניות (CJK).
הארגומנט content_type מציין אם פורמט התוכן הוא טקסט פשוט או HTML. משתמשים בהגדרות הבאות כדי להגדיר את content_type:
- כדי להגדיר טוקניזציה של טקסט, מגדירים את הארגומנט
content_typeלערךtext/plain. זו הגדרת ברירת המחדל. - כדי לבצע טוקניזציה של HTML, מגדירים את הארגומנט
content_typeלערך"text/html". בלי הארגומנט הזה, תגי HTML מטופלים כסימני פיסוק. במצב HTML, Spanner משתמש בהיוריסטיקה כדי להסיק עד כמה הטקסט בולט בדף. לדוגמה, אם הטקסט הוא כותרת או גודל הגופן שלו. המאפיינים הנתמכים ב-HTML כוללים אתsmall,medium,large,titleו-link. בדומה למאפיין position, המאפיין הזה מאוחסן לצד הטוקן באינדקס החיפוש. תהליך הטוקניזציה לא יוצר אסימונים לתגי HTML.
מאפייני הטוקן לא משפיעים על ההתאמה או על התוצאות של הפונקציה SEARCH או SEARCH_SUBSTRING. הם משמשים רק לדירוג.
בדוגמה הבאה אפשר לראות איך יוצרים טוקניזציה של טקסט:
GoogleSQL
CREATE TABLE T (
...
Text STRING(MAX),
Html STRING(MAX),
Text_Tokens TOKENLIST
AS (TOKENIZE_FULLTEXT(Text, content_type=>"text/plain")) HIDDEN,
Html_Tokens TOKENLIST
AS (TOKENIZE_FULLTEXT(Html, content_type=>"text/html")) HIDDEN
) PRIMARY KEY(...);
PostgreSQL
CREATE TABLE t (
...
text character varying,
html character varying,
text_tokens spanner.tokenlist
GENERATED ALWAYS AS (spanner.tokenize_fulltext(text, content_type=>"text/plain")) VIRTUAL HIDDEN,
html_tokens spanner.tokenlist
GENERATED ALWAYS AS (spanner.tokenize_fulltext(html, content_type=>'type/html')) VIRTUAL HIDDEN,
PRIMARY KEY(...));
שיפור זיהוי השפה באמצעות הארגומנט language_tag
כברירת מחדל, תהליך הטוקניזציה מזהה את שפת הקלט באופן אוטומטי. אם שפת הקלט ידועה, אפשר להשתמש בארגומנט language_tag כדי לשנות את ההתנהגות הזו:
GoogleSQL
AlbumTitle_Tokens TOKENLIST
AS (TOKENIZE_FULLTEXT(AlbumTitle, language_tag=>"en-us")) HIDDEN
PostgreSQL
albumtitle_tokens spanner.tokenlist
GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle, language_tag=>'en-us')) VIRTUAL HIDDEN
ברוב האפליקציות, הארגומנט language_tag לא מצוין, והן מסתמכות על זיהוי שפה אוטומטי. כדי לפלח שפות אסיאתיות כמו סינית, קוריאנית ויפנית, לא צריך להגדיר את שפת הטוקניזציה.
בדוגמאות הבאות אפשר לראות מקרים שבהם הפונקציה language_tag משפיעה על יצירת הטוקנים:
| פונקציה ליצירת טוקנים | טוקנים שנוצרו |
|---|---|
TOKENIZE_FULLTEXT("A tout pourquoi il y a un parce que") |
[a, tout, pourquoi, il, ya, un, parce, que] |
TOKENIZE_FULLTEXT("A tout pourquoi il y a un parce que", \ language_tag=>"fr") |
[a, tout, pourquoi, il, y, a, un, parce, que] |
TOKENIZE_FULLTEXT("旅 行") |
שני טוקנים: [旅, 行] |
TOKENIZE_FULLTEXT("旅 行", language_tag=>"zh") |
טוקן אחד: [旅行] |