# Aggregations — סטטיסטיקה על תוצאות חיפוש📖 שיעור

## מה זה?

"כמה מוצרים בכל קטגוריה?" ו"מה המחיר הממוצע לפי קטגוריה?" — אלה לא שאילתות חיפוש (`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 מחשב ערך (ממוצע, סכום) בתוך כל קבוצה

```json
// 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)
```

```json
// 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)
```

```json
// 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](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html)

---

## תרגילים

### תרגיל 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 ידניות.
