דירוג תוצאות החיפוש

בדף הזה מוסבר איך לדרג תוצאות חיפוש של חיפושי טקסט מלא ב-Spanner.

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

בדוגמה הבאה מוסבר איך לבצע חיפוש מדורג באמצעות הפונקציה SCORE:

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")
ORDER BY SCORE(AlbumTitle_Tokens, "fifth symphony") DESC

PostgreSQL

בדוגמה הזו משתמשים ב-spanner.search עם spanner.score.

SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'fifth symphony')
ORDER BY spanner.score(albumtitle_tokens, 'fifth symphony') DESC

דירוג מונחי שאילתה באמצעות הפונקציה SCORE

הפונקציה SCORE מחשבת ניקוד לכל מונח בשאילתה, ואז משלבת את הניקוד. הניקוד לכל מונח מבוסס בערך על תדירות המונח – תדירות מסמכים הופכית (TF/IDF). הניקוד הוא אחד מהרכיבים של הסדר הסופי של הרשומה. השאילתה משלבת אותו עם אותות אחרים, כמו מידת העדכניות שמשנה את ציון הרלוונטיות לנושא.

בהטמעה הנוכחית, החלק של IDF ב-TF/IDF זמין רק כשמשתמשים ב-enhance_query=>true. הוא מחשב את התדירות היחסית של מילים על סמך מאגר הנתונים המלא של האינטרנט שמשמש את חיפוש Google, ולא על סמך אינדקס חיפוש ספציפי. אם שיפור rquery לא מופעל, הניקוד משתמש רק ברכיב תדירות המונח (TF) (כלומר, מונח ה-IDF מוגדר ל-1).

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

בדרך כלל, ארגומנטים כמו query ו-enhance_query זהים בפונקציות SEARCH ו-SCORE כדי להבטיח עקביות באחזור ובדירוג.

הדרך המומלצת לעשות זאת היא להשתמש בארגומנטים האלה עם פרמטרים של שאילתה במקום עם מחרוזות מילוליות, ולציין את אותם פרמטרים של שאילתה בפונקציות SEARCH ו-SCORE.

מתן ציון למספר עמודות

‫Spanner משתמש בפונקציה SCORE כדי לתת ציון לכל שדה בנפרד. לאחר מכן, השאילתה משלבת את הציונים הנפרדים האלה. דרך נפוצה לעשות זאת היא לסכם את הציונים הנפרדים ואז להגדיל אותם בהתאם למשקלי השדות שסופקו על ידי המשתמש (שמסופקים באמצעות פרמטרים של שאילתת SQL).

לדוגמה, השאילתה הבאה משלבת את הפלט של שתי פונקציות SCORE:

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(Title_Tokens, @p1) OR SEARCH(Studio_Tokens, @p2)
ORDER BY SCORE(Title_Tokens, @p1) * @titleweight + SCORE(Studio_Tokens, @p2) * @studioweight
LIMIT 25

PostgreSQL

בדוגמה הזו נעשה שימוש בפרמטרים של שאילתה $1 ו-$2 שקשורים ל-"fifth symphony" ול-"blue note", בהתאמה.

SELECT albumid
FROM albums
WHERE spanner.search(title_tokens, $1) OR spanner.search(studio_tokens, $2)
ORDER BY spanner.score(title_tokens, $1) * $titleweight
        + spanner.score(studio_tokens, $2) * $studioweight
LIMIT 25

בדוגמה הבאה מוסיפים שני פרמטרים של חיזוק:

  • עדכניות (FreshnessBoost) מגדילה את הציון ב-(1 + @freshnessweight * GREATEST(0, 30 - DaysOld) / 30)
  • הפופולריות (PopularityBoost) מגדילה את הציון על ידי הכפלה שלו בפקטור (1 + IF(HasGrammy, @grammyweight, 0).

כדי שהשאילתה תהיה קריאה, היא משתמשת באופרטור WITH.

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(Title_Tokens, @p1) OR SEARCH(Studio_Tokens, @p2)
ORDER BY WITH(
  TitleScore AS SCORE(Title_Tokens, @p1) * @titleweight,
  StudioScore AS SCORE(Studio_Tokens, @p2) * @studioweight,
  DaysOld AS (UNIX_MICROS(CURRENT_TIMESTAMP()) - ReleaseTimestamp) / 8.64e+10,
  FreshnessBoost AS (1 + @freshnessweight * GREATEST(0, 30 - DaysOld) / 30),
  PopularityBoost AS (1 + IF(HasGrammy, @grammyweight, 0)),
  (TitleScore + StudioScore) * FreshnessBoost * PopularityBoost)
LIMIT 25

PostgreSQL

בדוגמה הזו נעשה שימוש בפרמטרים של שאילתה $1,‏ $2,‏ $3,‏ $4,‏ $5 ו-$6, שקשורים לערכים שצוינו בהתאמה ל-titlequery,‏ studioquery,‏ titleweight,‏ studioweight,‏ grammyweight ו-freshnessweight.

SELECT albumid
FROM
  (
    SELECT
      albumid,
      spanner.score(title_tokens, $1) * $3 AS titlescore,
      spanner.score(studio_tokens, $2) * $4 AS studioscore,
      (extract(epoch FROM current_timestamp) * 10e+6 - releasetimestamp) / 8.64e+10 AS daysold,
      (1 + CASE WHEN hasgrammy THEN $5 ELSE 0 END) AS popularityboost
    FROM albums
    WHERE spanner.search(title_tokens, $1) OR spanner.search(studio_tokens, $2)
  ) AS subquery
ORDER BY (subquery.TitleScore + subquery.studioscore)
  * (1 + $6 * greatest(0, 30 - subquery.daysold) / 30) * subquery.popularityboost
LIMIT 25

אפשר להשתמש ב-TOKENLIST_CONCAT גם בחיפוש וגם בדירוג כדי לפשט שאילתות במקרים המתאימים.

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(TOKENLIST_CONCAT([Title_Tokens, Studio_Tokens]), @p)
ORDER BY SCORE(TOKENLIST_CONCAT([Title_Tokens, Studio_Tokens]), @p)
LIMIT 25

PostgreSQL

בדוגמה הזו נשתמש ב-spanner.tokenlist_concat. פרמטר השאילתה $1 קשור ל-"blue note".

SELECT albumid
FROM albums
WHERE spanner.search(spanner.tokenlist_concat(ARRAY[title_tokens, studio_tokens]), $1)
ORDER BY spanner.score(spanner.tokenlist_concat(ARRAY[title_tokens, studio_tokens]), $1)
LIMIT 25

התאמות של סדר השאילתות לחיזוק

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

  1. ה-TOKENLIST מכיל את כל המונחים המקוריים בשאילתה.
  2. האסימונים צמודים זה לזה, ובאותו סדר שבו הם מופיעים בשאילתה.

יש כללים מיוחדים מסוימים למילות קישור, למילות שלילה ולביטויים:

  • שאילתה עם שלילה לא יכולה לקבל חיזוק של התאמה חלקית.
  • שאילתה עם מילת חיבור מקבלת חיזוק אם חלק ממילת החיבור מופיע במיקומים המתאימים.
  • שאילתה עם ביטוי מקבלת חיזוק אם הביטוי מופיע ב-TOKENLIST, והמונח שמשמאל לביטוי בשאילתה מופיע משמאל לביטוי ב-TOKENLIST, וכך גם לגבי המונח שמימין לביטוי.

‫Spanner מחיל חיזוק של התאמה מדויקת כשכל הכללים הקודמים מתקיימים, והאסימונים הראשון והאחרון בשאילתה הם האסימונים הראשון והאחרון במסמך.

מסמך לדוגמה: Bridge Over Troubled Water

שאילתה השיפור הופעל
גשר מעל מים סוערים ללא הגברה
גשר מעל – גוף מים אחר ללא חיזוק
Bridge (Over OR Troubled) Water ללא הגברה
גשר מעל הגברה חלקית
Bridge Over (Troubled OR Water) הגברה חלקית
Bridge Over Troubled Water הכפלה מדויקת
גשר על מים סוערים הכפלה מדויקת
Bridge ("Over Troubled" OR missingterm) Water הכפלה מדויקת

גרסאות של מודל הניקוד

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

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

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

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

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

הגדרת גרסת ברירת המחדל של מודל הניקוד של מסד הנתונים

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

GoogleSQL

מגדירים את האפשרות score_version של מסד הנתונים:

ALTER DATABASE database_name SET OPTIONS (score_version = 2)

PostgreSQL

מגדירים את האפשרות spanner.score_version של מסד הנתונים:

ALTER DATABASE database_name SET "spanner.score_version" = 2

הערכים התקינים לאפשרות של מסד הנתונים הם 1 או 2. אם הפרמטר version מופיע בבקשה, הוא מבטל את גרסת ברירת המחדל של מסד הנתונים.

שינוי גרסת הניקוד לכל שאילתה

אפשר לשנות את גרסת ברירת המחדל של מודל הניקוד לשאילתה ספציפית באמצעות הפרמטר version בארגומנט options של הפונקציה SCORE. אם בשאילתה מוגדרת גרסת מדרג, היא מבטלת את גרסת ברירת המחדל של מסד הנתונים.

בדוגמה הבאה, הגרסה שמוגדרת כברירת מחדל של מודל הניקוד מוחלפת על ידי ציון הערך version בפרמטר options:

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, @query)
ORDER BY SCORE(
  AlbumTitle_Tokens,
  @query,
  options=>JSON '{"version": 2}'
) DESC

PostgreSQL

בדוגמה הזו נעשה שימוש בפרמטר השאילתה $1 שקשור למחרוזת השאילתה.

SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, $1)
ORDER BY spanner.score(
  albumtitle_tokens,
  $1,
  options => '{"version": 2}'::jsonb
) DESC

הגבלת עומק האחזור

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

  1. ‫Retrieval depth limit (מגבלת עומק השליפה): מספר השורות המקסימלי לדירוג.
  2. Result set size limit: מספר השורות המקסימלי שהשאילתה אמורה להחזיר (בדרך כלל גודל הדף).

שאילתות יכולות להגביל את עומק השליפה באמצעות שאילתות משנה של SQL:

GoogleSQL

SELECT AlbumId
FROM
  (
    SELECT AlbumId, SCORE(Title_Tokens, @p1) AS score
    FROM Albums
    WHERE SEARCH(Title_Tokens, @p1)
    ORDER BY ReleaseTimestamp DESC
    LIMIT @retrieval_limit
  )
ORDER BY score DESC
LIMIT @page_size

PostgreSQL

בדוגמה הזו נעשה שימוש בפרמטרים של שאילתה $1, $2 ו-$3 שקשורים לערכים שצוינו בשביל title_query, retrieval_limit ו-page_size, בהתאמה.

SELECT albumid
FROM
  (
    SELECT albumid, spanner.score(title_tokens, $1) AS score
    FROM albums
    WHERE spanner.search(title_tokens, $1)
    ORDER BY releasetimestamp DESC
    LIMIT $2
  ) AS subquery
ORDER BY score DESC
LIMIT $3

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

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