text מול keyword
מה זה?
בשיעור הקודם הגדרנו name כ-text ו-category כ-keyword — בלי להסביר למה. זו לא בחירה שרירותית: text מפרק את התוכן למילים בודדות (Analysis) כדי לאפשר חיפוש “חכם”; keyword שומר את הערך כמו שהוא, שלם ומדויק, לחיפוש-מדויק ומיון. בחירה הפוכה (keyword על תיאור מוצר, text על קטגוריה) שוברת את שני סוגי הפעולות.
מילות מפתח שחשוב לזכור
• text — מנותח (Analyzed) למילים בודדות; מתאים לחיפוש חכם בתוכן חופשי (תיאורים, מאמרים)
• keyword — נשמר כמחרוזת שלמה ומדויקת, בלי ניתוח; מתאים לסינון מדויק, מיון, וקיבוץ (Aggregation)
• Analysis (ניתוח טקסט) — התהליך שהופך text למילים בודדות: פיצול למילים, המרה לאותיות קטנות, הסרת מילות-קישור
• Tokenization — שלב הפיצול עצמו בתהליך ה-Analysis, מטקסט שלם למילים (Tokens) נפרדות
// name (text) — "Adidas running shoes" is broken into tokens: ["adidas", "running", "shoes"]
// searching on any one of the words separately will find the document
GET /products/_search
{
"query": { "match": { "name": "running" } }
}
// finds "Adidas running shoes" — because "running" is one of the tokens// category (keyword) — "Footwear" is stored whole, not broken apart
// exact filtering — only an identical value matches
GET /products/_search
{
"query": { "term": { "category": "Footwear" } }
}
// finds only documents where category equals exactly "Footwear"
// "term": { "category": "Foot" } will find nothing — no exact match// A field with both mappings together — best of both worlds
PUT /products
{
"mappings": {
"properties": {
"name": {
"type": "text",
"fields": { "keyword": { "type": "keyword" } }
}
}
}
}
// name for smart search; name.keyword for exact filtering/sorting on the same fieldהסבר עיקרי
מתי text — כשרוצים “למצוא מסמכים שמכילים את המילה X” בלי קשר למיקום המדויק או לניסוח המלא — תיאורי מוצרים, תוכן מאמרים, כל טקסט חופשי שמישהו יחפש בתוכו חלקית. הניתוח (Analysis) הופך “נעלי ריצה אדידס” ל-3 טוקנים נפרדים, כך שחיפוש “ריצה” לבד עדיין מוצא את המסמך.
מתי keyword — כשרוצים התאמה מדויקת (קטגוריה, סטטוס, תג, מזהה), מיון לפי א’-ב’, או קיבוץ (Aggregation, בשיעור הבא) — “כמה מוצרים בכל קטגוריה” דורש שהערך יישאר שלם (“הנעלה”, לא “ה”+“נעלה” בנפרד), אחרת הקיבוץ יתפרק למילים בודדות חסרות משמעות.
השילוב (fields) הוא הפתרון המעשי הנפוץ ביותר — לפעמים רוצים גם חיפוש חכם וגם מיון/סינון מדויק על אותו שדה (למשל שם מוצר). ה-Mapping המשולב יוצר שני “צדדים” לאותו שדה: name (text, לחיפוש) ו-name.keyword (keyword, למיון/סינון מדויק) — שני שימושים, שדה מקור אחד.
יתרונות
text מאפשר חיפוש חכם וגמיש בתוכן חופשי; keyword נותן דיוק מלא לסינון/מיון/קיבוץ; המיפוי המשולב (fields) נותן את שני היתרונות על אותו שדה בלי כפילות נתונים.
חסרונות
בחירה שגויה (keyword על טקסט חופשי, או text על קטגוריה) שוברת שקטה את הפעולה המצופה, בלי שגיאה ברורה — רק תוצאות ריקות/לא-הגיוניות; המיפוי לא ניתן לשינוי בקלות אחרי יצירת ה-Index עם נתונים — דורש Reindex.
נקודות חשובות
• text = מנותח למילים, לחיפוש חכם; keyword = שלם ומדויק, לסינון/מיון/קיבוץ
• חיפוש term על שדה text (מנותח) לרוב לא מוצא כלום — term דורש התאמה מדויקת לטוקן
• fields מאפשר מיפוי כפול (name + name.keyword) לאותו שדה מקור
• קיבוץ (Aggregation) כמעט תמיד דורש keyword, לא text
טעויות נפוצות
• להגדיר קטגוריה/תג כ-text ולגלות שקיבוץ (Aggregation) מפרק אותם למילים בודדות חסרות הגיון
• להגדיר תיאור מוצר כ-keyword ולגלות שחיפוש חלקי לא מוצא כלום, כי נדרשת התאמה מדויקת לכל התיאור השלם
• להשתמש ב-term query על שדה text ולתהות למה תוצאה קיימת “לא נמצאת”
סיכום
text מנתח תוכן למילים בודדות (Tokenization), מתאים לחיפוש חכם בטקסט חופשי. keyword שומר ערך שלם ומדויק, מתאים לסינון, מיון וקיבוץ. הבחירה הלא-נכונה שוברת בשקט את הפעולה המצופה — לא שגיאה גלויה, אלא תוצאות ריקות או לא-הגיוניות. מיפוי משולב (fields) מאפשר גם חיפוש חכם וגם דיוק על אותו שדה מקור, כשצריך את שניהם.
דוקומנטציה רשמית
Elasticsearch — Text vs keyword
תרגילים
תרגיל 1 — הדגמת ההבדל
המשימה: על Index עם category כ-text, נסו קיבוץ (Aggregation בסיסי) עליה, וראו שהתוצאה “מפורקת” למילים בודדות במקום קטגוריות שלמות.
בדיקה: הקיבוץ מציג טוקנים חסרי-הגיון (מילים בודדות) במקום שמות קטגוריה שלמים — הוכחה לבעיה.
תרגיל 2 — מיפוי משולב
המשימה: הגדירו מחדש שדה name עם fields.keyword, והריצו חיפוש חכם על name וסינון מדויק על name.keyword על אותם נתונים.
בדיקה: name מוצא התאמות חלקיות (חיפוש חכם); name.keyword מוצא רק התאמה מדויקת לשלם — שני שימושים על אותו שדה מקור.
פרויקט מסכם
המשימה: תקנו Mapping שגוי ב-Index “מאמרים” (מהפרויקט המסכם הקודם) שבו tags הוגדר בטעות כ-text במקום keyword.
דרישות:
- זהו את הבעיה: הריצו קיבוץ על
tagsוהראו תוצאה שגויה - תקנו את ה-Mapping (
tagsכ-keyword), עם Reindex אם נדרש - הריצו שוב את הקיבוץ ואמתו תוצאה נכונה — תגים שלמים, לא מפורקים למילים
בדיקה: אחרי התיקון, הקיבוץ על tags מציג ערכי תג שלמים והגיוניים, לא מילים בודדות מפורקות.
מה בפרק הבא
בפרק הבא — שאילתות: match, term, range, bool: כלי החיפוש המרכזיים של Elasticsearch, כולל שילוב כמה תנאים יחד.