در قسمت قبل با برخی از دستورات CRUD کار کردیم اما هنوز بسیاری از مسائل باقی مانده است. من می خواهم در این قسمت به سراغ دستورات بیشتری بروم. ما تا اینجای کار با insertOne آشنا شده ایم و می دانیم که کارش تنها اضافه کردن یک document به collection مورد نظر شما است. حالا قرار است با insertMany آشنا شویم که چندین داده را به صورت یکجا وارد collection می کند. اکثر افراد تصور می کنند که insertMany چندین document را به صورت پارامتر های جداگانه می گیرد اما اینطور نیست. برای کار با insertMany باید داده هایتان را در قالب یک آرایه وارد آن کنید. مثلا آرایه زیر که دارای دو شیء JSON است برای این کار مناسب است:
[ { "departureAirport": "MUC", "arrivalAirport": "SFO", "aircraft": "Airbus A380", "distance": 12000, "intercontinental": true }, { "departureAirport": "LHR", "arrivalAirport": "TXL", "aircraft": "Airbus A320", "distance": 950, "intercontinental": false } ]
برای وارد کردن هر دو شیء با هم درون collection خودمان، از insertMany استفاده می کنیم. اگر در ویندوز از Cmder استفاده کنید، می توانید کد های آرایه بالا را به طور مستقیم کپی کرده و درون ترمینال paste کنید:
db.flightData.insertMany([ { "departureAirport": "MUC", "arrivalAirport": "SFO", "aircraft": "Airbus A380", "distance": 12000, "intercontinental": true }, { "departureAirport": "LHR", "arrivalAirport": "TXL", "aircraft": "Airbus A320", "distance": 950, "intercontinental": false } ])
فاصله های زیادی که بین اجزاء کد بالا می بینید به خاطر این است که کد را مستقیما کپی کرده ام و همانطور که دیدید، کد آرایه چند خطی بود اما ما در کنسول کد چند خطی نمی نویسیم. خوشبختانه Cmder اجازه این کار را به ما می دهد و کد بالا به طور صحیح وارد می شود. با اجرای این کد خروجی زیر را می گیریم:
"acknowledged" : true, "insertedIds" : [ ObjectId("5e8418e16d27a360fec5c8c9"), ObjectId("5e8418e16d27a360fec5c8ca") ]
بنابراین هر دو شیء ما با موفقیت ثبت شده اند.
تا این قسمت همیشه از find به صورت خالی و بدون آرگومان استفاده می کردیم تا همه document های موجود را برگرداند اما حالا می خواهیم از آرگومان اول آن استفاده کنیم: filter. حالا که دو شیء در collection خود داریم، می توانیم از find روی آن ها استفاده کنیم. مثلا اگر دستور زیر را اجرا کنیم هیچ خروجی نمی گیریم:
db.flightData.find({name: "Amir"})
آیا می دانید چرا؟ به دلیل اینکه در دو document ای که بالاتر وارد collection کردیم، هیچ خصوصیتی با این مقدار وجود ندارد بنابراین چیزی پیدا نمی شود. اما:
db.flightData.find({intercontinental: true}).pretty()
دستور pretty را فقط برای این اضافه کرده ام که خروجی بهتر نمایش داده شود. با اجرای این کد خروجی زیر را می گیریم:
"_id" : ObjectId("5e8418e16d27a360fec5c8c9"), "departureAirport" : "MUC", "arrivalAirport" : "SFO", "aircraft" : "Airbus A380", "distance" : 12000, "intercontinental" : true
حالا بگذارید فیلتر خود را پیشرفته تر کنیم. مثلا تمام پرواز هایی که طول پرواز آن ها از 10000 کیلومتر بیشتر باشد:
db.flightData.find({distance: {$gt: 10000}}).pretty()
دستور gt$ یک دستور خاص MongoDB است (هر دستوری که علامت دلار دارد، دستور خاصی از MongoDB است) که مخفف greater than (بیشتر از) می باشد. با اجرای این کد نتیجه زیر را می گیریم:
"_id" : ObjectId("5e8418e16d27a360fec5c8c9"), "departureAirport" : "MUC", "arrivalAirport" : "SFO", "aircraft" : "Airbus A380", "distance" : 12000, "intercontinental" : true
پرواز دیگر ما 950 کیلومتر بود بنابراین در نتیجه برگردانده نشده است. دستور زیر چطور؟
db.flightData.find({distance: {$gt: 900}}).pretty()
در این صورت هر دو پرواز برگردانده می شوند اما اگر از findOne استفاده کنیم چطور؟
db.flightData.findOne({distance: {$gt: 900}})
با اجرای این کد فقط اولین پرواز برگردانده می شود چرا که findOne همیشه اولین نتیجه را برمی گرداند. در ضمن در FindOne نمی توانید از pretty استفاده کنید.
فرض کنید بخواهیم یکی از اشیاء خود را بر اساس id آن پیدا کنیم و آن را ویرایش کنیم. در این صورت می توان گفت:
db.flightData.updateOne({_id: ObjectId("5e8418e16d27a360fec5c8c9")}, {$set: {delayed: true}})
این کد می گوید document ای با آیدی بالا را پیدا کن. توجه کنید که اگر id را خودمان به صورت دستی تعریف نکرده باشیم، حتما باید کل آن را در این قسمت قرار دهیم (یعنی فقط عدد را نگذارید بلکه ObjectId را کامل بنویسید). در جلسات قبل در مورد set$ نیز صحبت کردیم بنابراین از آن استفاده می کنید و خصوصیت delayed (تاخیر برای پرواز) را روی true می گذاریم. از آنجایی که این خصوصیت در document ما وجود ندارد، به صورت خودکار ساخته خواهد شد. با اجرای این کد خروجی زیر دریافت می شود:
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
بنابراین عملیات موفقیت آمیز بوده است و می توانید با find نتیجه تغییر را مشاهده کنید. البته اگر به جای updateOne از update استفاده کنیم چه می شود؟
db.flightData.update({_id: ObjectId("5e8418e16d27a360fec5c8c9")}, {$set: {delayed: false}})
با این کار، خصوصیت delayed دوباره False می شود. سوالی که مطرح می شود تفاوت بین update و updateMany و updateOne است. دستور updateOne فقط اولین document پیدا شده را تغییر می دهد، updateMany و update تمام document های پیدا شده را تغییر می دهند. با این حساب آیا update و updateMany یکی هستند؟ خیر. به دستور زیر نگاه کنید:
db.flightData.update({_id: ObjectId("5e8418e16d27a360fec5c8c9")}, {delayed: false})
من در این دستور، set$ را حذف کرده ام. اگر این کار را در updateOne و updateMany می کردیم، خطا دریافت می کردیم اما با update خطایی نمی گیریم. حالا اگر با find اشیاء موجود را بررسی کنیم، نتیجه زیر را می بینیم:
{ "_id" : ObjectId("5e8418e16d27a360fec5c8c9"), "delayed" : false } "_id" : ObjectId("5e8418e16d27a360fec5c8ca"), "departureAirport" : "LHR", "arrivalAirport" : "TXL", "aircraft" : "Airbus A320", "distance" : 950, "intercontinental" : false }
تفاوت update این است! همانطور که می بینید document اول ما به طور کامل با شیء پاس داده شده جایگزین شده است بنابراین فقط id و delayed باقی مانده اند! البته پیشنهاد می کنم که اگر می خواهید داده ها را به این شکل تغییر دهید (کلا جایگزین نمایید) از replaceOne استفاده کنید:
db.flightData.replaceOne({_id: ObjectId("5e8418e16d27a360fec5c8c9")}, { "departureAirport": "MUC", "arrivalAirport": "SFO", "aircraft": "Airbus A380", "distance": 12000, "intercontinental": true })
با این کار document اول به حالت قبلی خود برمی گردد. یادتان باشد که این روش امن تر است و همچنین تمام روش های ذکر شده به id دست نمی زنند و آن را همانطور که هست نگه می دارند.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.