Skip to main content

elasticsearch for dummies (hebrew) - part 2 - the document

המסמך

בחלק 1 של מבוא ל elasticsearch נאמר כי elasticsearch הוא database שיודע לשמור מסמכים ולחפש בהם בצורה מאוד מהירה.

אז מה זה מסמך?

כאשר שומעים את המילה "מסמך" (document) ישר קופץ לראש מסמך וורד או מסמך PDF שיש בו הרבה טקסט ותמונות. לא מדובר פה בכזה מסמך.

מסמך ב elasticsearch הוא אוסף של שדות. כל שדה יכול להכיל מחרוזת או מספר. שדה יכול להכיל מערך של ערכים. שדה גם יכול להיות שדה "מורכב" כך שהוא בעצמו מכיל אוסף שדות. חשוב לזכור שבמקרה והשדה מחזיק מחרוזת זה לא אומר בהכרח שמדובר בטקסט פשוט. יכול להיות שהמחרוזת הזו היא בעצם תאור של תאריך או תאור של סכום כספי.

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

הצורה השכיחה להציג מסמך כזה היא שימוש בפורמט json. דוגמא:




לאחר שיוצרים אינדקס, אפשר לאנדקס מסמכים, למחוק מסמכים מהאינדקס, לעדכן מסמכים ולחפש מסמכים.

שמירת מסמך ב database

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

למי שרגיל לדטאבייס רלציוני (RDB) אז אפשר להסתכל על מסמך כאל רשומת מידע, להסתכל על אינדקס כאל סכימה ואז הכנסת מסמך לאינדקס היא כמו הוספת רשומה לסכימה. לקורא שרגיל ל RDB חסר מייד האנלוגיה לטבלה (רשומה מוכנסת לטבלה ב RDB). אל דאגה – יש ב elastissearch משהו שדומה לטבלה. הוא יתואר באחד המדריכים הבאים (המושג נקרא mapping).

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

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

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

חשוב לדעת שכל מסמך שמאונדקס מקבל מספר מזהה אוטומטית. המספר הזה נשמר בשדה _id. אפשר להשתמש במזהה הזה אח"כ כדי להגיע למסמך. המשתמש ב ES יכול לתת בעצמו מזהה לכל מסמך ולא להשאיר ל ES את הצורך לקבוע את המזהה. דוגמא למקרה כזה – אם כל מסמך מתאר מידע על עובד, אז המשתמש אולי ירצה שהמזהה יהיה מספר עובד ולא סתם מספר רץ.

דוגמא להכנסת מסמך:


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

דוגמא נוספת, והפעם מציינים את המזהה בבקשה עצמה. עכשיו פקודת ה REST צריכה להיות PUT:


עדכון מסמך

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

לכל מסמך שהוכנס מתווסף אוטומטית שדה _version שמחזיק את מספר הגרסה. בהתחלה הוא 1 ובכל עדכון, העותק החדש של המסמך מקבל מספר גדול ב 1 כגרסה שלו.

כדי לעדכן, שומרים עותק מלא של המסמך שוב תוך שימוש במזהה של המסמך המקורי:




בתשובה רואים שמספר הגרסה עלה ב 1:



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

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


מחיקת מסמך

כמובן שאפשר גם למחוק מסמך וזאת ע"י בקשת DELETE:


אם המסמך קיים אז מקבלים תשובה עם קוד 200 (OK) אחרת מקבלים תשובה עם קוד 404 (Not Found).
כמו עדכון, הפעולה הזו רק מסמנת המסמך למחיקה והוא יימחק מהדיסק מתשהוא בעתיד.

נעילות

נשאלת השאלה מה קורה כאשר מעדכנים אותו מסמך משני מקורות שונים. מה תופס? איך אפשר לזהות זאת?

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

דוגמא אחרת: אם שני המקורות קוראים בו זמנית את המסמך וכל אחד חושב שהוא היחיד שמעדכן את המסמך.



כדי להתמודד עם המצב הזה ב databases הומצא מנגנון הנעילות.

RDB בדר"כ משתמש בנעילה "פסימיסטית", כלומר הוא מניח שקונפליקטים יכולים להתרחש בצורה תדירה ולכן ברגע שהוא ניגש לרשומה, הוא חוסם אותה לגישה נוספת ממקור אחר עד שמסיים את העדכון של הרשומה.

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

כל המנגנון הזה משתמש בשדה _version של המסמך כדי לדעת האם הוא השתנה.

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

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



אם מישהו בינתיים עדכן את המסמך אז מספר הגרסה שלו יהיה שונה ופעולת העדכון שלנו תיכשל. זאת התשובה שנקבל:



עד כאן לשלב זה. בחלק הבא נעבור כיצד מחפשים מידע ב DB, הרי זה כל המטרה ...

Comments

Popular posts from this blog

Best freeware - XML editor

As a software developer, I open XML files all the time. I a heavy commercial XML editor. But nothing can compare to a small, thin and free XML editor like 'foxe'. A great feature is has is the alignment of long XML strings to readable XML format (Shift-F8). It help lot of times when the XML file was generated by some tool and was not readable. Homepage: http://www.firstobject.com/dn_editor.htm

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')