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

בדף הזה מוסבר איך לדרג תוצאות של חיפושים בטקסט מלא ב-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, ולא על סמך אינדקס חיפוש ספציפי. אם ההגדרה 'שיפור שאילתות' לא מופעלת, הניקוד מבוסס רק על רכיב תדירות המונח (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) AND 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) AND 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) AND 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) AND 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 Troubled ללא חימום מוגבר
Bridge Over - other water ללא חימום מוגבר
Bridge (Over OR Troubled) Water ללא חימום מוגבר
Bridge Over הגברה חלקית
Bridge Over (Troubled OR Water) הגברה חלקית
Bridge Over Troubled Water הגדלה מדויקת
הגשר 'מעל מים סוערים' הגדלה מדויקת
גשר ("מעל מים סוערים" או missingterm) הגדלה מדויקת

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

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

  1. מגבלת עומק האחזור: מספר השורות המקסימלי לניקוד.
  2. מגבלת גודל של קבוצת תוצאות: המספר המקסימלי של שורות שהשאילתה צריכה להחזיר (בדרך כלל גודל הדף).

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

GoogleSQL

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

PostgreSQL

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

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

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

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