Skip to main content

elasticsearch - מבוא חלק 3 - חיפוש


איך מבצעים חיפוש ב ElasticSearch - מבוא בסיסי


עד עכשיו הכנסנו מידע ל elasticsearch (בהמשך ייכתב ES בקיצור). הגיע הזמן שנחפש אותו ...

Types

אבל לפני שמתחיל לחפש נתאר עוד מושג חשוב ב ES והוא type. המושג הזה מאפשר לחלק את המסמכים שמוכנסים ל ES לקבוצות שונות. כלומר, אפשר להגיד ל ES בזמן הכנסת מסמך שהוא בעל type מסויים.


לדוגמא: נבנה אינדקס עבור מסעדה ונאנדקס בו תאור של כל המנות תחת type שנקרא dish, נאנדקס מידע על המלצרים תחת type שנקרא waiters ונאנדקס מידע על ספקים תחת type שנקרא supplier.

זה מה שמאפשר לנו אח"כ לחפש מידע מסוג מסויים. נוח!

הכנסת מסמך עם ציון הסוג שלו:

דוגמא:


ובמקרה שרוצים לתת ל ES לקבוע בעצמו את מזהה המסמך:

נחזור לחיפוש

לחיפוש יש שני API-ים שונים.. אחד פשוט ומהיר שמיועד בעיקר לאנשים שרוצים להריץ שאילתא. השני הוא מובנה ומיועד לתוכנית שפונה ל ES.  בשני המקרים צריך לציין איפה לחפש. זאת מציינים בשורת ה URL:

כדי לחפש באינדקס מסויים נרשום בשורת ה URL:
GET /indexName/_search

כדי לחפש בסוג מסויים באינדקס:
GET /indexName/typeName/_search

כדי לחפש בכל האינקסים שמתחילים בתוים מסויימים:
GET /indexPrefix*/_search

ויש עוד אפשרויות שונות.

חיפוש מהיר - query string

בחיפוש מהיר מתארים במחרוזת אחת את השאילתא, מחרוזת אחת כמו שיש למשל ב where של שאילתת SQL. אפשר לרשום את המחרוזת הזאת בשורת ה URL וזה ממש נוח כאשר אדם עובד מול ES ורוצה לבצע חיפושים:


בדוגמא הזו, ES יחפש במסמכים בעלי סוג בשם tweet בכל האינדקסים את המסמכים בעלי שדה tweet שמכיל את המילה elasticsearch.

הנה דוגמא לביצוע החיפוש המהיר שאינו דרך שורת ה URL וזאת דרך פקודת simple_query_string


אפשר גם לציין כמה קריטריונים לחיפוש. אם שמים מחרוזת כזו בשורת ה URL אז צריך לבצע מה שנקרא percent encoding כדי להפוך אותך למחרוזת רציפה אחת.

דוגמא: התנאי name:john +tweet:mary+ אומר שיש למצוא מסמכים שבשדה name מופיעה המילה john ובשדה tweet מופיעה המילה mary. כדי לשים את הביטוי בשורת ה URL צריך לקודד אותו ל %2Bname%3Ajohn+%2Btweet%3Amary.



והנה שורת החיפוש (דוגמא לאתר שיעשה את זה בקלות - http://www.url-encode-decode.com/)


סימן '+' מציין כי יש למצוא את המילה. סימן '-' מציין כי אסור שתהיה המילה. כל המילים שאין לפניהן '+' או '-' הן מילים אופציונליות. ככל שיותר מילים כאה יימצאו כך הניקוד של המסמך תעלה (כלומר, המיקום שלו ברשימת התשובות תהיה גבוהה יותר).

אפשר גם לחפש בכל השדות ע"י ציון מילות החיפוש בלבד ללא ציון שם שדה לחיפוש.

GET /_search?q=mary

מאחורי הקלעים, ES מחפש את המילים הללו בשדה שהוא מייצר ששמו _all. הוא שם בשדה שרשרור של כל השדות. דרך אגב, אם השדה _all אינו דרוש אפשר להגיד ל ES לא לייצר אותו.

דוגמא מורכבת יותר:



חיפוש "מלא" - DSL

שפת החיפוש הקלה שנקראית query-string search או query lite נוחה מאוד לחיפושים אנושיים על ה DB. תוכנית לעומת זו זקוקה ל API מסודר. וזה גם קיים ב ES. בשיטה הזו, משתמשים בפקודה _search ומעבירים בגוף הבקשה תאור של השאילתא דרך json. 

אנקדוטה מעניינת היא שפעולת החיפוש נעשית ע"י HTTP GET. וזה בתורו מעלה שאלה, איך אפשר לתת ל GET מידע נוסף ב body? ואכן, ישנם שרתים, במיוחד שרתי פרוקסי שלא יעבירו את ה body. במקרה כזה, ES מאפשר להשתמש גם ב HTTP POST לבצע את החיפוש.

הסיבה שב ES בחרו להשתמש ב HTTP GET היא שזה יותר מתאים לפעולה, הרי היא לא משנה כלום בנתונים.

דוגמא לשאילתא:

ודוגמא יותר מורכבת:

במקרה הזה יש אופטור bool שמרכיב תתי שאליתות. על כל תת שאילתא מציינים האם היא חייבים להתקיים או לא.

מה מוזר ושונה בחיפוש

מי שרגיל לעבוד ב SQL אז הוא\היא יגלו שהחיפוש ב ES מתנהג אחרת.

קודם כל, החיפוש דומה למה שגוגל עושה - כלומר מחזיר את התשובות מסודרות לפי ניקוד של מידת ההתאמה לתנאי החיפוש. לדוגמא, אם בחיפוש צוינו שתי מילים אז ככל שהמילים קרובות יותר זה לזה אז הניקוד יותר גבוה. מסמך שיש בו רק מילה אחת, גם יחזור אבל עם ניקוד מאוד נמוך.

דוגמא:




חוץ מזה, תמיד יחזרו עד 10 תשובות אפילו אם יש יותר מסמכים רלבנטים. מוזר! הסיבה היא ש ES עובד תמיד עם Paging. כלומר, כאשר מבצעים חיפוש ולא מציינים מספר דף, אז יחזור הדף הראשון. אבל אפשר לבקש דף אחר ע"י פרמטר.

דוגמא:



שדה from הוא ה offset של התשובה מהתשובה הראשונה. שדה size מציין כמה מסמכים להביא.

מה לעשות כאשר רוצים לעבוד כמו ב SQL רגיל ולקבל רק מסמכים שעונים על תנאי מסויים? אז צריך לציין שהתנאי הוא filter. יש שדה מיוחד לכך בבקשת החיפוש.

דוגמא:



בדוגמא הזו יש שילוב - קודם ES מפלטר את המסמכים ורק על מה שנשאר, יריץ חיפוש בסגנון גוגל.




הערה: הסיכום מסתמך בעיקר על הספר Elasticsearch - The Definitive Guide

Comments

Popular posts from this blog

Jenkins error: groovy.lang.MissingPropertyException

I tried to run groovy build step and got below error. This post will describe how I solved the problem.

Caught: groovy.lang.MissingPropertyException: No such property: hudson for class: script


SSL in pictures

Here is my summary on SSL (or as I like to call it 'SSL for dummies')