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 מחשב ערך (ממוצע, סכום) בתוך כל קבוצה
// 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 — כל אחד בתחביר שונה לגמרי לאותה בעיה.
דוקומנטציה רשמית
תרגילים
תרגיל 1 — terms בסיסי
המשימה: על Index products, הריצו terms Aggregation לפי category, עם "size": 0.
בדיקה: התוצאה מציגה כל קטגוריה עם מספר המוצרים הנכון בה, בלי מסמכים מלאים בתגובה.
תרגיל 2 — Bucket + Metric
המשימה: הוסיפו Metric avg על price בתוך ה-terms Aggregation מתרגיל 1.
בדיקה: כל קטגוריה מציגה גם כמות וגם מחיר ממוצע נכון.
פרויקט מסכם
המשימה: בנו לוח סטטיסטיקה מלא ל-Index Articles.
דרישות:
termsAggregation לפיtags, עם ספירת מאמרים לכל תג- Metric מקונן — תאריך פרסום מינימלי ומקסימלי (
min/maxעלpublishDate) בתוך כל תג - שילוב עם
query— הסטטיסטיקה מחושבת רק על מאמרים שאינםarchived(מ-must_notבשיעור הקודם)
בדיקה: התוצאה מציגה לכל תג את כמות המאמרים וטווח התאריכים הנכון, רק מבין מאמרים לא-מאורכבים.
מה בפרק הבא
בפרק הבא — קונטיינר בסיסי ו-C# Client: איך מריצים Elasticsearch ב-Docker (מיחידה קודמת) ומתחברים אליו מקוד C#, לא רק דרך שאילתות JSON ידניות.