تا این قسمت تمام دستورات CREATE و READ و UPDATE را بررسی کردیم و حالا نوبت به بررسی DELETE است. در واقع DELETE آنچنان پیچیدگی های خاصی ندارد بنابراین می توانیم تمام مسائل آن را در یک قسمت تمام کنیم. ما در این قسمت از پایگاه داده user و کالکشن users استفاده می کنیم اما شما می توانید از هر پایگاه داده و کالکشنی که دوست دارید استفاده کنید. البته قبل از شروع این جلسه حتما از داده های خود backup بگیرید تا اگر چیزی را به اشتباه حذف کردید بتوانید آن را برگردانید.
اگر بخواهیم فقط یک سند را حذف کنیم باید از دستور DeleteOne استفاده نماییم. این دستور یک فیلتر را می گیرد و اولین نتیجه ای را که بر اساس آن فیلتر پیدا کند، حذف خواهد کرد. توجه داشته باشید که این فیلتر دقیقا مانند همان فیلتری است که در فصل READ از آن استفاده می کردیم بنابراین می توانید تمام مسائلی را که در آنجا توضیح دادیم، در این قسمت نیز استفاده کنید. مثلا شما می توانید هر سه مقدار نام، سن و id را در یک فیلتر بررسی کنید یا اینکه یک فیلتر بسیار ساده داشته باشید:
db.users.deleteOne({name: "Pooya"})
این دستور اولین فردی که اسم Pooya را داشته باشد حذف خواهد کرد. البته این دستور می تواند آرگومان دومی را نیز بگیرد که writeConcern است. اگر یادتان باشد WriteConcern را برای دستورات insert توضیح داده بودیم و گفتیم که:
ما می توانیم خصوصیتی به نام writeConcern را برای دستورات Write خود (مثلا insertOne و updateOne و غیره) تعریف کنیم که چنین شکلی دارد:
{w: 1, j: undefined}
حرف w یعنی write و مشخص می کند که چند instance (نمونه) از سرورِ MongoDB باید این دستور را تایید کنند (ما می توانیم چندین نمونه از سرور های MongoDB را روی یک سرور میزبانی داشته باشیم که بحث آن مربوط به فصل های آینده می شود و فعلا کاری با آن نداریم). به طور خلاصه w:1 (حالت پیش فرض) یعنی سرورِ MongoDB من باید این دستور Write را قبول کند تا storage Engine از آن مطلع باشد و نهایتا داده هایتان را روی دیسک ذخیره کند.
حرف j مخفف journal است. فایل journal یک فایل جداگانه است که تحت مدیریت storage engine می باشد که شبیه یک فایل todo است (لیستی از کار هایی که باید انجام شوند). یعنی لیستی از کار هایی است که storage engine باید انجام بدهد (مثلا دستور insertOne من را بعدا روی دیسک نیز ذخیره کند تا فقط در مموری نماند). البته من توضیح دادم که دستور write و قبول شدن آن برای ذخیره سازی داده ها در دیسک کافی است بنابراین دیگر چه نیازی به این فایل است؟ فرض کنید در حین انجام عملیات (مثلا insertMany) سرور ما از کار بیفتد (در چنین حالتی ممکن است مموری کاملا پاک شود). دستوراتی که در مموری بودند و هنوز به دیسک منتقل نشده اند چه خواهند شد؟ فایل journal این کار ها را ذخیره می کند تا پس از راه اندازی و بالا آمدنِ دوباره سرور، کوئری ادامه پیدا کند.
اگر می خواهید journal را فعال کنید باید گزینه آن را به شکل J: true قرار بدهیم. یعنی فقط زمانی به من گزارش موفقیت آمیز بودن کوئری را بده که هم سرورِ MongoDB آن را تایید کرده باشد (w: 1) و هم در journal ذخیره شده باشد (j: true). البته می توانیم آن را به شکل زیر بنویسیم:
{w:1, wtimeout: 200, j: true}
خصوصیت wtimeout یعنی چقدر به سرور زمان می دهیم که گزارش موفقیت آمیز بودن را ارسال کند. اگر از این زمان بیشتر شود، کل دستور لغو خواهد شد. در مورد استفاده از این دستور باید مراقب باشید چرا که اگر زمان بسیار کمی را تعیین کنید دستورات سالم خود را کنسل خواهید کرد. پیشنهاد من این است که اگر هدف خاصی ندارید، از این گزینه استفاده نکنید. همچنین یادتان باشد که اگر journal را فعال کنید، دستورات write شما کمی بیشتر زمان می برند و فعال کردن یا نکردن آن بستگی به سلیقه شما و نظرتان دارد.
تمام این مسائل برای DeleteOne نیز صادق است و می توانید writeConcern را تعیین کنید گرچه که پیشنهاد می شود WriteConcern را دستکاری نکنید مگر اینکه هدفی کاملا مشخص داشته باشید. بنابراین با اجرای کوئری ساده زیر، کاربر Pooya حذف می شود:
db.users.deleteOne({name: "Pooya"})
من چند نمونه کوئری دیگر را نیز به شما نشان می دهم. مثلا اگر بخواهیم تمام افرادی را حذف کنیم که سن بیشتر از 30 سال داشته و isSporty هستند:
db.users.deleteMany({totalAge: {$gt: 30}, isSporty: true})
این کوئری هیچ سندی را پاک نمی کند چرا که چنین فردی را نداریم. حالا می گوییم هر فردی که totalAge را ندارد حذف شود:
db.users.deleteMany({totalAge: {$exists: false}, isSporty: true})
حالا اگر بخواهیم تمام اسناد (document) یک collection را حذف کنیم باید فیلتر را خالی بگذاریم. به کوئری زیر توجه کنید:
db.users.deleteMany({})
با اجرای این دستور هیچ سندی در کالکشن ما باقی نمی ماند و دستور زیر نیز هیچ چیزی را برنمی گرداند:
db.users.find().pretty()
این برای زمانی بود که می خواهید خود collection باقی بماند. اگر بخواهید collection نیز حذف شود باید به شکل زیر عمل کنیم:
db.users.drop()
متد drop کل collection را حذف می کند اما باید به شدت مراقب چنین دستوراتی باشید چرا که می توانند صدمات جبران ناپذیری را به کسب و کار شما ایجاد کنند. معمولا دستور هایی مانند drop برای استفاده system administrator و مدیر پایگاه داده هستند تا ساختار های کلی را طراحی کنند و در برنامه های واقعی (مثل یک وب سایت) تقریبا هیچ وقت چنین دستوری را استفاده نمی کنیم. اگر دستور بالا با موفقیت collection را حذف کند، true را برمی گرداند اما اگر مشکلی پیش بیاید (مثلا چنین collection ای وجود نداشته باشد) آنگاه false برگردانده خواهد شد.
مشابه این دستور برای حذف کردن کل پایگاه داده نیز وجود دارد:
db.dropDatabase()
دستور dropDatabase دقیقا باید روی db صدا زده شود و چیزی بینشان نباشد.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.