ایندکس‌های unique و انجام sorting

Unique Indexes and Sorting

24 اردیبهشت 1401
درسنامه درس 52 از سری دوره جامع آموزش MongoDB
MongoDB: ایندکس های unique و انجام sorting (قسمت 54)

تا این قسمت از این دوره آموزشی از index ها فقط برای find (پیدا کردن اطلاعات) استفاده کرده ایم اما باید بدانید که ایندکس ها در sorting (مرتب کردن داده ها) نیز مفید هستند. چرا؟ به دلیل اینکه ایندکس ها یک لیست ترتیبی (ordered list) هستند بنابراین MongoDB می تواند از این لیست برای مرتب کردن داده ها استفاده کند، البته به شرطی که بخواهید داده ها را دقیقا با استفاده از لیست ایندکس مرتب کنید. من برای شما یک مثال می زنم:

db.contacts.explain().find({"dob.age": 35}).sort({gender: 1})

کوئری بالا افراد 35 ساله را گرفته و سپس آن ها را بر اساس سن و به صورت صعودی (کم به زیاد) مرتب می کند. با اجرای کوئری بالا مثل همیشه گزارش explain را می گیریم که در آن "stage" برابر "IXSCAN" است، یعنی عملیات ما از ایندکس ها استفاده کرده است و سرعت بهتری گرفته است. برای اینکه بدانیم برای کدام فیلد (gender یا age) از ایندکس استفاده شده است، باید به قسمت "indexBounds" در گزارش explain مراجعه کنیم:

"indexBounds" : {                  
        "dob.age" : [              
                "[35.0, 35.0]"     
        ],                         
        "gender" : [               
                "[MinKey, MaxKey]" 
        ]                          
}                                  

یعنی هم برای age و هم برای gender از ایندکس استفاده شده است. با اینکه من فقط به دنبال age بودم (قسمت find) اما MongoDB از اطلاعات gender برای مرتب کردن داده ها استفاده کرده است.

نکته مهم دیگری که باید حتما به آن توجه کنید، در مورد sort کردن داده های بدون ایندکس است. اگر داده های شما بسیار بزرگ باشد (مثلا 70 درصد کالکشن را برگردانید) و از ایندکس ها نیز استفاده نکنید، احتمال time out شدن زیاد است. time out شدن یعنی درخواست آنقدر طول می کشد که سرور یا موتور MongoDB آن را قطع می کند. چرا؟ به دلیل اینکه MongoDB فقط 32 مگابایت فضا را در مموری برای دریافت و مرتب کردن داده ها رزرو می کند بنابراین اگر index نداشته باشیم، MongoDB باید تمام اسناد شما را گرفته و در مموری قرار دهد و سپس sort را در آنجا (درون مموری) انجام بدهد. حالا اگر داده های شما بسیار زیاد باشد (میلیون ها سند)، احتمال دارد که time out کنید. بنابراین index ها فقط برای پیدا کردن داده ها نیستند، بلکه برای sort کردن در داده های بسیار بزرگ ضروری می باشند. البته پایگاه داده ما به طور کل 5 هزار سند دارد که برای MongoDB بسیار کوچک محسوب می شود و هیچ گاه به حد 32 مگابایت نخواهیم رسید.

حالا می خواهم شما را به چند جلسه قبل ببرم. اگر یادتان باشد در یکی از جلسات ایندکس زیر را ساخته بودیم:

db.contacts.createIndex({"dob.age": 1})

با اجرای کوئری بالا نتیجه زیر برای ما نمایش داده می شود:

"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,                  
"numIndexesAfter" : 2,                   
"ok" : 1                           

numIndexesBefore مشخص می کند که قبل از ساخت این index چند index داشته ایم که 1 بوده است اما اگر یادتان باشد در همان جلسه گفتیم که این اولین ایندکس ما است و اصلا قبل از آن ایندکسی نداشته ایم! برای مشاهده تمام ایندکس های یک کالکشن می توانیم از متد getIndexes روی آن کالکشن استفاده کنیم:

db.contacts.getIndexes()

با اجرای این کوئری گزارشی به شکل زیر می گیریم:

{                                         
         "v" : 2,                          
         "key" : {                         
                 "_id" : 1                 
         },                                
         "name" : "_id_",                  
         "ns" : "contactData.contacts"     
 },                                        
 {                                         
         "v" : 2,                          
         "key" : {                         
                 "dob.age" : 1,            
                 "gender" : 1              
         },                                
         "name" : "dob.age_1_gender_1",    
         "ns" : "contactData.contacts"     
 }                                         

همانطور که می بینید، ما دو index را در کالکشن contacts داریم. اولین index، همان ایندکس پیش فرضی است که MongoDB به صورت خودکار روی id_ قرار می دهد و دومی index ترکیبی خودمان است. شما هر کالکشنی را که ایجاد کنید، MongoDB به صورت خودکار فیلد id را ساخته و آن را index می کند.

پیکربندی index ها

تا اینجای کار یاد گرفتیم که index مربوط به فیلد id_ (با فیلد id که توسط خودمان تعریف شده تفاوت دارد) به صورت خودکار توسط MongoDB ایجاد می شود و unique است؛ یعنی یکتا و منحصر به فرد است و نمی توانیم یک id_ با مقدار تکراری داشته باشیم. برخی اوقات این قابلیت unique بودن را برای فیلد های مورد نظر خود نیز می خواهیم. مثلا Email کاربران نباید تکراری باشد و اصلا منطقی نیست که کسی با یک ایمیل دو بار ثبت نام کند! به همین دلیل باید آن را unique کنیم. برای پیکربندی index ها کافی است شیء ای را که حاوی تنظیمات است به عنوان آرگومان دوم به آن پاس بدهیم:

db.contacts.createIndex({email: 1}, {unique: true})

با اجرای کوئری بالا یک خطا می گیریم!

        "ok" : 0,
        "errmsg" : "E11000 duplicate key error collection: contactData.contacts index: email_1 dup key: { email: \"abigail.clark@example.com\" }",
        "code" : 11000,
        "codeName" : "DuplicateKey",
        "keyPattern" : {
                "email" : 1
        },
        "keyValue" : {
                "email" : "abigail.clark@example.com"
        }
}

این خطا به ما می گوید که فعلا نمی توانیم فیلد email را unique کنیم چرا که کاربری با نام abigail.clark@example.com دو بار یا بیشتر در پایگاه داده ما وجود دارد. بنابراین اگر مقادیر ما از قبل وارد پایگاه داده شده باشند و تکراری نیز باشند، نمی توانیم آن فیلد را unique کنیم. برای تست کردن این موضوع می توانیم کوئری زیر را اجرا کنیم:

db.contacts.find({email: "abigail.clark@example.com"}).count()

این کوئری نتیجه 2 را به ما می دهد که یعنی دو کاربر با این ایمیل وجود دارند. کاربر اول بدین شکل است:

"_id" : ObjectId("5eb8ff52abf8f8026baa9e81"),
        "gender" : "female",
        "name" : {
                "title" : "mrs",
                "first" : "abigail",
                "last" : "clark"
        },
// بقیه داده ها //

کاربر دوم:

        "_id" : ObjectId("5eb8ff52abf8f8026baa983a"),
        "gender" : "female",
        "name" : {
                "title" : "miss",
                "first" : "abigail",
                "last" : "clark"
        },

همانطور که می بینید id_ های این دو کاربر با هم متفاوت است چرا که توسط خود MongoDB ساخته شده اند و باید unique باشند بنابراین نمی توانند تکراری باشند اما ایمیل چنین شرطی را نداشته است بنابراین دچار مشکل شده ایم. هدف من از این مثال این بود که بدانید چطور می توانید خصوصیات unique را تعریف کرده و با مفهوم آن ها آشنا شوید.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری دوره جامع آموزش MongoDB توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

مقالات مرتبط
آخرین سوالات کاربران
5451218 در 4 سال قبل پرسیده:
ما را دنبال کنید
اینستاگرام روکسو تلگرام روکسو ایمیل و خبرنامه روکسو