# שאילתות — match, term, range ו-bool📖 שיעור

## מה זה?

בשיעורים הקודמים ראינו טעימות מ-`match` ו-`term`. עכשיו — התמונה המלאה: `match` לחיפוש חכם על `text`, `term` להתאמה מדויקת על `keyword`, `range` לטווחים מספריים/תאריכים, ו-`bool` לשילוב כמה תנאים יחד — בדיוק כמו `&`/`|` ב-Pandas, או `Where` מורכב ב-LINQ, רק בתחביר JSON ייעודי ל-Elasticsearch.

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

• `match` — חיפוש חכם על שדה `text`; מוצא מסמכים שמכילים חלק מהמילים, מדורגים לפי רלוונטיות

• `term` — התאמה מדויקת על שדה `keyword` (או מספר/בוליאני); לא "מבין" משמעות, רק שוויון מדויק

• `range` — סינון לפי טווח (`gte`, `lte`, `gt`, `lt`) — מספרים, תאריכים

• `bool` — שילוב כמה תנאים: `must` (חובה, כמו AND), `should` (מומלץ, כמו OR), `must_not` (שלילה)

```json
// match — smart search
GET /products/_search
{
  "query": { "match": { "name": "running shoes" } }
}
// finds documents that contain at least some of the words, ranked by how many words match
```

```json
// range — price range
GET /products/_search
{
  "query": {
    "range": { "price": { "gte": 100, "lte": 500 } }
  }
}
// only products priced between 100 and 500
```

```json
// bool — combining conditions, like a compound Where in LINQ
GET /products/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "name": "shoes" } }
      ],
      "filter": [
        { "term": { "category": "Footwear" } },
        { "range": { "price": { "lte": 500 } } }
      ],
      "must_not": [
        { "term": { "inStock": false } }
      ]
    }
  }
}
// must contain "shoes" in the name, be in the "Footwear" category, cost up to 500, and not be out of stock
```

## הסבר עיקרי

`must` מול `filter` — שניהם "חובה" (כמו AND), אבל `must` **משפיע על הדירוג** (Relevance Score — כמה טוב ההתאמה), בעוד `filter` **רק מסנן**, בלי להשפיע על הדירוג — ומהיר יותר כי Elasticsearch יכול לשמור אותו ב-Cache. הכלל המעשי: תנאי טקסט חופשי (`match`) שמשפיע על "כמה רלוונטי" שייך ל-`must`; תנאי מדויק (קטגוריה, טווח מחיר) שרק "כן/לא" שייך ל-`filter`.

`bool` הוא בדיוק כמו `&`/`|` ב-Pandas — `must` (כולם חייבים להתקיים) מקביל ל-`&`; `should` (לפחות אחד, ותורם לדירוג אם יש יותר) מקביל בערך ל-`|` עם משקל; `must_not` הוא שלילה מפורשת. השם שונה, הרעיון הלוגי (AND/OR/NOT) זהה לגמרי לכל מה שכבר נלמד.

`range` על תאריכים עובד כמו על מספרים — `{"range": {"publishDate": {"gte": "2026-01-01"}}}` מסנן לפי תאריכים בדיוק כמו טווח מחירים — כל עוד השדה מוגדר כ-`date` ב-Mapping (מה שנלמד בשיעור הראשון של היחידה).

## יתרונות

`match`/`term`/`range` מכסים את רוב תרחישי החיפוש הבסיסיים בממשק ברור; `bool` משלב תנאים מורכבים בקריאות טובה; הפרדת `must`/`filter` נותנת גם דיוק דירוג וגם ביצועים טובים.

## חסרונות

תחביר JSON מקונן (`bool` בתוך `query` בתוך הבקשה) יכול להיות מסורבל לקריאה עם הרבה תנאים; שימוש שגוי ב-`must` במקום `filter` (או להפך) פוגע בביצועים או בדירוג בלי שגיאה גלויה.

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

• `match` = חיפוש חכם על text; `term` = התאמה מדויקת על keyword

• `range` = טווחים, עם `gte`/`lte`/`gt`/`lt`

• `bool` משלב: `must`≈AND (משפיע על דירוג), `filter`≈AND (לא משפיע, מהיר יותר), `must_not`≈NOT

• `filter` עדיף על `must` כשלא צריך את התנאי להשפיע על דירוג רלוונטיות

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

• להשתמש ב-`term` על שדה `text` — לרוב לא מוצא כלום כי השדה מנותח, לא שלם

• לשים כל תנאי תחת `must` גם כשהוא לא צריך להשפיע על דירוג — פגיעה בביצועים מיותרת

• לשכוח ש-`range` על תאריכים דורש פורמט תאריך תואם למה שהוגדר ב-Mapping

## סיכום

`match` מבצע חיפוש חכם על שדות `text`; `term` מבצע התאמה מדויקת על `keyword`; `range` מסנן לפי טווחים מספריים/תאריכים. `bool` משלב את כולם — `must`/`filter` (AND, כאשר `filter` לא משפיע על דירוג ומהיר יותר), `should` (OR), ו-`must_not` (NOT). זהו ארגז הכלים המרכזי לכל שאילתת חיפוש אמיתית ב-Elasticsearch.

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

[Elasticsearch — Query DSL](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html)

---

## תרגילים

### תרגיל 1 — match ו-range נפרדים

**המשימה:** על Index `products`, כתבו שאילתת `match` שמוצאת מוצרים לפי מילה בשם, ושאילתת `range` נפרדת שמוצאת מוצרים בטווח מחירים.

**בדיקה:** כל שאילתה מחזירה תוצאות נכונות בנפרד.

### תרגיל 2 — bool משולב

**המשימה:** שלבו את שתי השאילתות מתרגיל 1 יחד עם `bool`, כאשר החיפוש בשם ב-`must` והטווח ב-`filter`.

**בדיקה:** התוצאה כוללת רק מוצרים שעונים על שני התנאים יחד.

---

## פרויקט מסכם

**המשימה:** בנו endpoint חיפוש "מתקדם" ל-Index `Articles` (מהפרויקט המסכם הקודם).

**דרישות:**
1. `match` על `content`/`title` לפי מונח חיפוש חופשי מהמשתמש
2. `filter` עם `term` על `tags` (סינון קטגוריה) ו-`range` על `publishDate` (טווח תאריכים)
3. `must_not` שמסנן החוצה מאמרים עם תג `"archived"`

**בדיקה:** שאילתה עם כל התנאים יחד מחזירה רק מאמרים שעונים על כולם בו-זמנית; שינוי כל תנאי בנפרד משנה את התוצאה בהתאם.

## מה בפרק הבא

בפרק הבא — **Aggregations**: איך מחשבים סטטיסטיקה על תוצאות חיפוש (ממוצע, קיבוץ, ספירה) — בדיוק כמו `GroupBy`/`agg` שכבר מוכר, בתחביר Elasticsearch.
