در این جلسه و جلسه بعدی می خواهیم در رابطه با تعریف ایندکس ها صحبت کنیم. برای تعریف ایندکس ها دو پروتکل یا روش اصلی وجود دارد:
هر چیزی که از ابتدای این فصل تا به حال یاد گرفته ایم به صورت مستقیم (در foreground) بوده است چرا که از دستور CreateIndex استفاده کرده ایم که مخصوص تعریف ایندکس ها است. از آنجایی که ساخت ایندکس ها سرعت بسیار بالایی دارد ما متوجه فرآیندی به نام collection lock (به معنی «قفل شدن کالکشن») نمی شویم. در واقع زمانی که قرار است برای یک کالکشن به صورت مستقیم ایندکس تعریف کنیم، کل کالکشن قفل می شود و هیچ دستور دیگری را قبول نمی کند. این مسئله برای تعریف غیر مستقیم ایندکس ها برعکس است و اگر ایندکس خودتان را به صورت غیر مستقیم تعریف کنید (در حالی که ایندکس ها در حال ساخته شدن هستند) کالکشن قفل نشده و می توانید به آن کوئری بزنید. البته مزیت روش مستقیم این است که ساخت ایندکس ها در آن سریع تر است در حالی که برای ساخت ایندکس ها در background (به طور غیر مستقیم) باید زمان بیشتری صرف شود.
احتمالا از خودتان می پرسید با این حساب چرا باید از روش غیر مستقیم یا پس زمینه (background) برای تعریف ایندکس ها استفاده کنیم؟ پاسخ ساده است! ما همیشه در حال طراحی سایت از صفر نیستیم. طراحی اولیه یک سایت فقط قدم اول است و پس از آن با انواع و اقسام به روز رسانی ها یا ویرایش های مختلف روبرو خواهیم بود. حالا تصور کنید که وب سایت ما چند ماه در حال کار کردن است و می خواهیم یک ایندکس به آن اضافه کنیم. اگر از روش مستقیم استفاده کنیم، کالکشن ما قفل می شود و کاربران نمی توانند از سایت استفاده کنند (گرچه معمولا این مدت، مدت بسیار کوتاهی است) بنابراین برای سایتی که در حالت production (استفاده عموم) است، روش background گزینه بهتری محسوب می شود.
برای اینکه با تفاوت این دو روش در عمل آشنا شویم باید فایل آماده ای را که برایتان قرار داده ام از لینک زیر دانلود کنید:
دانلود فایل جاوا اسکریپتی برای ایجاد یک میلیون document
این فایل جاوا اسکریپتی یک حلقه ساده در خود دارد که یک میلیون سند را به کالکشن شما اضافه می کند. اگر دوست دارید محتویات آن را ببینید، به کد زیر نگاه کنید:
conn = new Mongo(); db = conn.getDB("credit"); for (let i = 0; i < 1000000; i++) { db.ratings.insertOne({ "person_id": i + 1, "score": Math.random() * 100, "age": Math.floor(Math.random() * 70) + 18 }) }
این کد یک نمونه از Mongo می سازد و سپس پایگاه داده credit را پیدا می کند (ما چنین پایگاه داده ای نداریم بنابراین برایمان ساخته می شود). سپس یک حلقه ساده For را داریم که 1 میلیون بار گردش کرده و هر دفعه یک کاربر جدید را به کالکشن ratings اضافه می کند. این کالکشن نیز وجود ندارد بنابراین به صورت خودکار ساخته خواهد شد. اجرای این دستور بسته به سیستم شما چندین دقیقه طول خواهد کشید (1 میلیون ردیف تعداد بسیار زیادی است بنابراین می توان انتظار 10 تا 25 دقیقه را داشت). من از عمد تعداد گردش ها را روی 1 میلیون گذاشته ام تا داده های حجیمی داشته باشیم و فرق آن ها را متوجه بشوید اما اگر دوست دارید داده های کمتری را داشته باشید، می توانید حلقه ساده For را در فایل credit-rating.js (فایلی که برای دانلود گذاشته ام) تغییر دهید. مثلا 500 هزار تا کافی است. همچنین اگر سیستم شما هنگ کرد یا از منتظر ماندن خسته شدید، می توانید کلید های Ctrl + C را زده یا ترمینال را ببندید تا اجرای این اسکریپت کاملا متوقف شود.
احتمالا تعجب کرده اید که این فایل جاوا اسکریپتی چطور در MongoDB اجرا خواهد شد اما واقعیت این است که MongoDB برای اجرای این فایل ها مشکلی ندارد و می تواند فایل های جاوا اسکریپتی شما را بدون مشکل روی سرور اجرا کند. ابتدا یک پنجره ترمینال را در مسیر فایل credit-rating.js باز کنید. سپس دستور زیر را در آن اجرا کنید:
mongo credit-rating.js
زمانی که اجرای این اسکریپت تمام شد می توانیم دستور Show dbs را اجرا کنیم تا ببینیم آیا پایگاه داده Credit ایجاد شده است یا خیر؟ اگر ایجاد شده بود یعنی همه چیز بدون مشکل انجام شده است و حالا می توانیم از آن استفاده کنیم:
use credit
سپس دستور show collections را اجرا کنید تا ببینیم کالکشن ratings به آن اضافه شده است یا خیر. اگر اضافه شده بود، برای تست می توانید دستور زیر را نیز اجرا کنید تا تعداد سند های موجود در این کالکشن را مشاهده کنید:
db.ratings.count()
با اجرای این دستور عدد 1000000 نمایش داده خواهد شد که یعنی یک میلیون سند در این کالکشن موجود است. اگر فایل credit-rating.js را تغییر داده باشید یا میان اجرای این اسکریپت آن را قطع کرده باشید، تعداد این سند ها نیز متفاوت خواهد بود. برای مشاهده ساختار اسناد درون این کالکشن می توانیم از یک کوئری find ساده استفاده کنیم:
db.ratings.findOne()
نتیجه برگردانده شده برای من به شکل زیر است:
"_id" : ObjectId("5ebfe1ee15d4667bc590befc"), "person_id" : 1, "score" : 9.568823573984254, "age" : 72
یعنی هر نفر یک id دارد که خودمان person_id نام گذاری کرده ایم و جدا از id تولید شده به صورت خودکار توسط MongoDB است. سپس یک score داریم که یک عدد تصادفی را دارد (ربطی به score درون meta$ و تولید شده توسط MongoDB ندارد) و سپس age را داریم که آن هم یک عدد تصادفی است. در جلسه بعد هر دو حالت foreground و background را روی آن پیاده سازی می کنیم.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.