מה זה?

“כמה מוצרים בכל קטגוריה?” ו"מה המחיר הממוצע לפי קטגוריה?" — אלה לא שאילתות חיפוש (match/term), אלה שאלות אנליטיות. Aggregations פותרות את זה — הרעיון הרביעי (אחרי LINQ GroupBy, MongoDB $group, Pandas groupby+agg) של אותה בעיה בדיוק: קיבוץ וחישוב סטטיסטי, הפעם על תוצאות חיפוש ב-Elasticsearch.

מילות מפתח שחשוב לזכור

• Aggregation — חישוב סטטיסטי (סכום, ממוצע, ספירה, קיבוץ) על תוצאות שאילתה, לא רק שליפת מסמכים

• terms Aggregation — מקבץ לפי ערכי שדה keyword (בדיוק כמו GROUP BY) — מחזיר “דלי” (Bucket) לכל ערך ייחודי

• avg/sum/min/max Aggregation — חישוב סטטיסטי ישיר על שדה מספרי

• Bucket מול Metric — Bucket מקבץ מסמכים לקבוצות; Metric מחשב ערך (ממוצע, סכום) בתוך כל קבוצה

// terms Aggregation — grouping by category, like GROUP BY
GET /products/_search
{
  "size": 0,
  "aggs": {
    "by_category": {
      "terms": { "field": "category" }
    }
  }
}
// result: for each category — how many products it has (automatic count per Bucket)
// Combining Bucket + Metric — average price within each category
GET /products/_search
{
  "size": 0,
  "aggs": {
    "by_category": {
      "terms": { "field": "category" },
      "aggs": {
        "avg_price": { "avg": { "field": "price" } }
      }
    }
  }
}
// for each category: product count (automatic) + average price (nested Metric)
// Combining with query — aggregation only on filtered results
GET /products/_search
{
  "size": 0,
  "query": { "term": { "inStock": true } },
  "aggs": {
    "by_category": { "terms": { "field": "category" } }
  }
}
// grouping only on in-stock products, not the whole Index

הסבר עיקרי

"size": 0 — למה אפס תוצאות? — כשמעניינת רק הסטטיסטיקה (לא המסמכים הבודדים עצמם), "size": 0 אומר “אל תחזיר לי מסמכים, רק את תוצאת ה-Aggregation” — חוסך רוחב-פס ועיבוד מיותר של תוצאות שממילא לא נשתמש בהן.

Bucket מול Metric — בדיוק כמו groupby (מכין קבוצות, Bucket) ו-agg (מחשב בתוכן, Metric) ב-Pandas — terms יוצר Bucket לכל ערך ייחודי (כל קטגוריה מקבלת “תא” נפרד), ו-avg/sum המקוננים בתוכו הם ה-Metric שמחושב בתוך כל Bucket בנפרד. אפשר לקנן עוד Aggregations בתוך Bucket, בדיוק כמו ש-agg() יכול לחשב כמה סטטיסטיקות בו-זמנית.

Aggregation + Query יחד — כמו ש-$match לפני $group ב-MongoDB (מיחידה קודמת) מסנן לפני שמקבצים, כך גם כאן: query מסנן את המסמכים לפני שה-aggs מחשבת עליהם — קיבוץ על “רק מוצרים במלאי” ולא על כל ה-Index כולו.

יתרונות

Aggregations נותנות סטטיסטיקה מלאה בשאילתה אחת, בלי לשלוף את כל הנתונים ולעבד ידנית בקוד; שילוב Bucket+Metric נותן תובנות רב-שכבתיות (קיבוץ + חישוב) בבקשה אחת; משולבות בקלות עם query לסינון מקדים.

חסרונות

Aggregations על שדות עם הרבה ערכים ייחודיים (High Cardinality) עלולות להיות כבדות; terms על שדה text (במקום keyword) חוזרת לבעיה מהשיעור השני — קיבוץ שבור.

נקודות חשובות

• Aggregation = חישוב סטטיסטי על תוצאות, לא שליפת מסמכים — לרוב עם "size": 0

• terms = Bucket, מקביל ל-GROUP BY/groupby; avg/sum = Metric, מקביל ל-agg

• Aggregations מקוננות מאפשרות Bucket עם Metric בתוכו (קיבוץ + חישוב יחד)

• query מסנן לפני ש-aggs מחשבת — בדיוק כמו $match לפני $group

טעויות נפוצות

• לשכוח "size": 0 ולקבל גם את כל המסמכים המלאים בתגובה, גם כשרק הסטטיסטיקה מעניינת

• להריץ terms על שדה text במקום keyword — קיבוץ מפורק למילים בודדות, שוב

• לשכוח לשלב query לפני aggs כשרוצים לחשב רק על תת-קבוצה מסוננת, לא כל ה-Index

סיכום

Aggregations מחשבות סטטיסטיקה על תוצאות ב-Elasticsearch — terms יוצר Bucket לפי ערכי שדה (כמו GROUP BY), ו-Metrics כמו avg/sum מחושבים בתוך כל Bucket. שילוב query+aggs מאפשר לחשב סטטיסטיקה רק על תת-קבוצה מסוננת. זו הפעם הרביעית בקורס שאותו רעיון בדיוק (קיבוץ+חישוב) מופיע — LINQ, MongoDB, Pandas, ועכשיו Elasticsearch — כל אחד בתחביר שונה לגמרי לאותה בעיה.

דוקומנטציה רשמית

Elasticsearch — Aggregations


תרגילים

תרגיל 1 — terms בסיסי

המשימה: על Index products, הריצו terms Aggregation לפי category, עם "size": 0.

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

תרגיל 2 — Bucket + Metric

המשימה: הוסיפו Metric avg על price בתוך ה-terms Aggregation מתרגיל 1.

בדיקה: כל קטגוריה מציגה גם כמות וגם מחיר ממוצע נכון.


פרויקט מסכם

המשימה: בנו לוח סטטיסטיקה מלא ל-Index Articles.

דרישות:

  1. terms Aggregation לפי tags, עם ספירת מאמרים לכל תג
  2. Metric מקונן — תאריך פרסום מינימלי ומקסימלי (min/max על publishDate) בתוך כל תג
  3. שילוב עם query — הסטטיסטיקה מחושבת רק על מאמרים שאינם archived (מ-must_not בשיעור הקודם)

בדיקה: התוצאה מציגה לכל תג את כמות המאמרים וטווח התאריכים הנכון, רק מבין מאמרים לא-מאורכבים.

מה בפרק הבא

בפרק הבא — קונטיינר בסיסי ו-C# Client: איך מריצים Elasticsearch ב-Docker (מיחידה קודמת) ומתחברים אליו מקוד C#, לא רק דרך שאילתות JSON ידניות.