יצירת טוקנים

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

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

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

  • כל טוקנייזר הוא פונקציית 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 and JSONB tokenizers (TOKENIZE_JSON ו-TOKENIZE_JSONB) משמשים ליצירת קבוצה של טוקנים שמאיצים את השוואת ה-JSON, את ההכלה ואת פרדיקטים של קיום מפתח, כמו doc.key = "value" או doc[@key] IS NOT NULL (GoogleSQL) ו-doc->'key' = '"value"'::jsonb או doc ? 'key' (PostgreSQL).

בדרך כלל משתמשים בפונקציות של טוקניזציה בביטוי של עמודה שנוצרה. העמודות האלה מוגדרות כ-HIDDEN כדי שלא ייכללו בתוצאות השאילתה של SELECT *.

בדוגמה הבאה נעשה שימוש ב-tokenizer של טקסט מלא וב-tokenizer מספרי כדי ליצור מסד נתונים שמאחסן שמות ודירוגים של אלבומי מוזיקה. הצהרת ה-DDL מבצעת שני דברים:

  1. מגדיר את עמודות הנתונים AlbumTitle ו-Rating.
  2. מגדיר את 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 משתמשת בפונקציה TOKENIZE_FULLTEXT כדי ליצור אסימונים מ-AlbumTitles בטבלה Albums. הצהרת ה-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'. בדומה למיקום, המאפיין מאוחסן לצד האסימון באינדקס החיפוש. הטוקניזציה לא יוצרת אסימונים לתגי 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") טוקן אחד: [旅行]

המאמרים הבאים