במאמר הקודם למדנו על שליפת נתונים מתקדמת יותר, במאמר הזה נקח את כל הסיפור צעד אחד קדימה ונלמד איך שולפים נתונים באופן יותר מתקדם.
ראשית – projection. זה נשמע כמו משהו מאוד מאיים אבל האמת היא שזה ממש פשוט. בגדול – זה לשלוף את הנתונים שאתה צריך ורק אותם. אם נתרגם את זה לשפת ה-MySQL אז במקום להשתמש ב * SELECT, אנו משתמשים בבחירה יותר מדויקת – ואם אי פעם כתבתם שאילתה ב-MySQL אז זה לא אמור להפחיד אתכם.
מה זאת אומרת? לא תמיד אני רוצה לקבל את כל האוביקט. בואו ונסתכל למשל על collectio clients שאיתו עבדנו בדוגמאות הקודמות ויש הוראות לייצר אותו במדריכים הקודמים. איך הוא נראה? מאה רשומות של משהו כזה:
{ "_id" : ObjectId("541d9aee784269c2e9f3c092"), "x" : 17, "name" : "gIZxF4ALvwiMMtvtZC8G6ExsmxQum8KFAQws4z6un9nMrol8QCCue7T7rCLVvnNM0dfVzW3VKZgEeS5PLKA6RNI7lZbWT1ySl8v1xb77nmCasF3I8Vr5Vu3Bqa0uDv8umXkbreihE1DXl2OrudxEmUPMf0PKSdQhHe5zqqQ90LOBBwd6lNBGhmeLkI1ramDC4i7JnnfmTrX8v61e", "value" : 34.991921903565526 }
{ "_id" : ObjectId("541d9aee784269c2e9f3c093"), "x" : 18, "name" : "e683H4QlB2sHLGUtvnftDpWQTJJgZ2Ev92TRTEK5oiCbLxsz2d5tS0hx4fKZqzfITMrtlDJkI4R2RRMhvT4wngOulcTnb9t8SnfDytSIplJUhly", "value" : 25.878882687538862 }
{ "_id" : ObjectId("541d9aee784269c2e9f3c094"), "x" : 19, "name" : "HIIWTKsT8guLtyMkgf3KVmCzJNUviArxVT9GaT4vI3Bkg3AZLWzMoMGVynoQz1qp0elVk0oyxdx7fUUFFRWNRtUJipf95WhKGQu3UDkRb2XFigmuhGnVc5WNbCg1w", "value" : 96.42805075272918 }
נניח ואני רוצה למצוא את ה-document שה-id שלו הוא 541d9aee784269c2e9f3c092. אני רק מזכיר לכם שמדובר ב-id ש-MongoDB מעניק באופן אוטומטי ל-documents. אם עברתם עד עכשיו את המדריכים לא תתעלפו אם אני אומר לכם שאפשר לקבל את האובייקט באמצעות שאילתת find כזו:
db.clients.find({_id : ObjectId("541d9aee784269c2e9f3c092")});
השימוש במתודת ObjectId הכרחי אם משתמשים ב-ID כזה. אבל אין פה משהו שמפתיע. כשאני מריץ כזה דבר, אני מקבל את כל ה-document.
{ "_id" : ObjectId("541d9aee784269c2e9f3c092"), "x" : 17, "name" : "gIZxF4ALvwiMMtvtZC8G6ExsmxQum8KFAQws4z6un9nMrol8QCCue7T7rCLVvnNM0dfVzW3VKZgEeS5PLKA6RNI7lZbWT1ySl8v1xb77nmCasF3I8Vr5Vu3Bqa0uDv8umXkbreihE1DXl2OrudxEmUPMf0PKSdQhHe5zqqQ90LOBBwd6lNBGhmeLkI1ramDC4i7JnnfmTrX8v61e", "value" : 34.991921903565526 }
> db.clients.find({_id : ObjectId("541d9aee784269c2e9f3c092")});
אבל מה קורה אם אני צריך רק את השם? אין לי מה לעשות עם כל ה-document. ואם מדובר ב-document ארוך ומייגע, יש מצב שזה יהיה מאוד בזבזני להעביר לי את כל המידע. מה עושים? משהו כזה:
db.clients.find({_id : ObjectId("541d9aee784269c2e9f3c092")},{name:true});
פשוט מעבירים עוד ארגומנט שהוא אובייקט חביב שבו אני מציין true ליד כל תכונה של ה-document שאני רוצה.
ואם אני רוצה יותר? אין בעיה, אפשר להעביר משהו כזה:
db.clients.find({_id : ObjectId("541d9aee784269c2e9f3c092")},{name:true, x:true});
וכך מקבלים בדיוק את מה שרוצים. הבטחתי ש-projection יהיה פשוט, לא?
ואם כבר מדברים על דברים פשוטים, בואו ונדבר על sorting. הרבה פעמים, אם אנחנו מקבלים כמה documents, אנו רוצים לקבל את הרשימה ממויינת. למשל, אם אני רוצה את כל אלו שה-x שלהם קטן מ-5, אני רוצה לקבל אותם לא לפי הסדר שהם הוכנסו ל-collection אלא לפי סדר אלפאביתי של השם שלהם. למשל. בדיוק בשביל זה אני צריך מיון לתוצאות. עם MongoSB זה קל ופשוט. כל מה שאני צריך לעשות זה להוסיף מתודה אחרי ה-find. למתודה קוראים sort והארגומנט שלה הוא אובייקט חביב שכולל שתי תכונות: הראשונה היא שם השדה שאנו ממיינים לפיו והשניה היא 1- או 1 – לסדר יורד או עולה. למשל:
db.clients.find({x:{$lt:5}},{name:true, x:true}).sort({"name":1});
במקרה הזה אני ממיין לפי name את התוצאה של כל הקליינטים שה-x שלהם נמוך מ-5. חדי העין שביניכן יבחינו שעשינו גם projection, כי לא בא לי לקבל את כל האובייקט. אם לא הייתי רוצה projection, זה היה נראה כך:
db.clients.find({x:{$lt:5}}).sort({"name":1});
מיון זה קל ופשוט. נכון? אותו הדבר גם עם הגבלה (LIMIT). משתמשים בהגבלה בהרבה מאוד מקרים. למשל, הרבה פעמים אני רוצה רק את החמישה הראשונים וכל השאר לא מעניינים אותי. אם ניקח את השאילתה שלעיל – בוא ונגיד שאני רוצה רק את השניים העליונים לאחר המיון. איך עושים את זה? פשוט מוסיפים מתודת limit שמקבלת מספר. איזה מספר? המספר שאותו אני רוצה. והנה הדוגמה המיוחלת:
db.clients.find({x:{$lt:5}},{name:true, x:true}).sort({"name":-1}).limit(2)
פשוט, לא? כך משרשרים את המתודות (מאוד דומה ל-jQuery כמובן, אבל לא רק). איזה כיף, כמה נעים ונוח. אם אני רוצה OFFSET – שזה בעצם לדלג על כמה תוצאות ולהתחיל את ההגבלה מהתוצאה השניה (שימושי במיוחד לעימוד – למשל לקבל את התוצאות 1-10 ואז את 11-20 וכך הלאה והלאה) אז משתמשים במתודת skip שגם היא מקבלת מספר.
db.clients.find({x:{$lt:5}},{name:true, x:true}).sort({"name":-1}).limit(2).skip(2);
ואם קראתם את כל המדריכים עד עכשיו, כולל את זה – אז השורה למעלה לא תראה לכם נורא נורא מאיימת. כי בסך הכל יש פה db (זוכרים שעשינו לו use?) ואז ה-collection ואז find שמקבל אובייקט תנאי וגם אנחנו אומרים לו בדיוק מה אנחנו רוצים שיראה (במקרה הזה את ה-name ואת ה-x). את התוצאה אנו ממיינים בסדר יורד לפי ה-name, מקבלים רק 2 תוצאות (אפילו שיש יותר) בזכות ה-LIMIT, אבל אנחנו לא מקבלים את שתי התוצאות הראשונות אלא את השתיים הבאים בתור בגלל ה-skip.
טוב, אולי זה בכל זאת קצת מאיים – שווה לתרגל ולראות שהשד לא נורא כל כך.
במאמר הבא אנו נדבר על עדכון של נתונים ב-MongoDB.
3 תגובות
אתר מצויין
חשוב שיש הסבר טוב בעברית
שלום
האתר מצוין ממש
מה קורה אם הוא לא מוצא את מה שביקשתי וחוזר מערך ריק?
איך בודקים לפני זה אם הוא יחזיר מערך ריק?
הסברים תותחים וברורים.
ממש ממש תודה! זה עזר לי מאד.
קשה למצוא מדריכים ברורים בעברית על החומר הזה.