معرفی

MongoDB یک سیستم مدیریت پایگاه داده مبتنی بر سند است که به شما امکان می دهد حجم زیادی از داده ها را در اسناد ذخیره کنید که از نظر اندازه و ساختار متفاوت است. MongoDB دارای یک مکانیزم پرس و جو قوی است که به شما امکان می دهد اسناد را بر اساس معیارهای خاص فیلتر کنید. با افزایش مجموعه MongoDB ، جستجوی اسناد می تواند مانند جستجوی سوزن در انبار کاه باشد.

انعطاف پذیری که MongoDB در رابطه با پرس و جوها ارائه می دهد ، می تواند موتور پایگاه داده را پیش بینی کند که چه نوع پرس و جوهایی بیشتر مورد استفاده قرار می گیرد. بدون توجه به اندازه مجموعه باید آماده یافتن اسناد باشد. به همین دلیل ، مقدار داده های موجود در یک مجموعه به طور مستقیم بر عملکرد جستجو تأثیر می گذارد: هرچه مجموعه داده بزرگتر باشد ، پیدا کردن اسناد مطابق با پرس و جو برای MongoDB دشوارتر است.

فهرست ها یکی از ضروری ترین ابزارهایی هستند که مدیر پایگاه داده می تواند برای کمک آگاهانه به موتور پایگاه داده و بهبود عملکرد آن استفاده کند. در این آموزش ، شما خواهید آموخت که نمایه ها چیست ، چگونه آنها را ایجاد کنید و چگونه نحوه استفاده از آنها را هنگام انجام داده ها در پایگاه داده بررسی کنید.

پیش نیازها

برای پیگیری این آموزش ، شما نیاز دارید:

  • سروری با کاربر معمولی و غیر روت با امتیازات sudo و فایروال با UFW پیکربندی شده است. این آموزش با استفاده از سروری که Ubuntu 20.04 را اجرا می کند تأیید شده است و می توانید با دنبال کردن این آموزش راه اندازی اولیه سرور برای اوبونتو 20.04 ، سرور خود را آماده کنید.
  • MongoDB روی سرور شما نصب شده است. برای تنظیم این ، آموزش ما را در مورد نحوه نصب MongoDB در اوبونتو 20.04 دنبال کنید.
  • نمونه MongoDB سرور شما با فعال کردن احراز هویت و ایجاد یک کاربر مدیریتی ایمن می شود. برای ایمن سازی MongoDB مانند این ، آموزش ما را در مورد نحوه ایمن سازی MongoDB در اوبونتو 20.04 دنبال کنید.
  • آشنایی با عملیات MongoDB CRUD و بازیابی اشیاء از مجموعه ها به طور خاص. برای یادگیری نحوه استفاده از پوسته MongoDB برای انجام عملیات CRUD ، آموزش نحوه انجام عملیات CRUD در MongoDB را دنبال کنید.

فهمیدن شاخص ها

به طور معمول ، هنگامی که از پایگاه داده MongoDB برای بازیابی اسناد مطابقت با شرایط خاصی – مانند قله های کوه با ارتفاع بیش از 8000 متر – درخواست می کنید ، پایگاه داده باید اسکن مجموعه ای را برای پیدا کردن آنها انجام دهد. این بدان معناست که هر سند را از مجموعه بازیابی می کند تا بررسی کند که آیا آنها با شرایط مطابقت دارند یا خیر. اگر سندی با شرایط مطابقت داشته باشد ، به لیست اسناد برگشتی اضافه می شود. اگر سندی با شرایط تعیین شده مطابقت نداشته باشد ، MongoDB تا زمانی که اسکن کل مجموعه را به پایان نرساند ، به سراغ اسکن سند بعدی می رود.

این مکانیسم برای بسیاری از موارد استفاده خوب عمل می کند ، اما هنگامی که مجموعه بزرگتر می شود ، می تواند بطور قابل توجهی کند شود. اگر اسناد ذخیره شده در مجموعه پیچیده باشند ، این امر واضح تر می شود. اگر اسناد مجموعه بیش از چند فیلد نباشد ، خواندن و سپس تجزیه و تحلیل محتویات آنها می تواند هزینه بر باشد.

نمایه ها ساختارهای داده خاصی هستند که تنها زیرمجموعه کوچکی از داده های موجود در اسناد مجموعه را جدا از خود اسناد ذخیره می کنند. در MongoDB ، آنها به گونه ای پیاده سازی شده اند که پایگاه داده می تواند هنگام جستجوی مقادیر به سرعت و به طور م themثر از آنها عبور کند.

برای کمک به درک نمایه ها ، مجموعه ای از پایگاه داده را که محصولات را در یک فروشگاه آنلاین ذخیره می کند تصور کنید. هر محصول با یک سند حاوی تصاویر ، توضیحات دقیق ، روابط دسته و بسیاری از زمینه های دیگر نشان داده شده است. برنامه اغلب یک پرس و جو علیه این مجموعه برای بررسی محصولات موجود در انبار اجرا می کند.

بدون هیچ نمایه ای ، MongoDB باید همه محصولات را از مجموعه بازیابی کرده و اطلاعات موجودی موجود در ساختار سند را بررسی کند. با این حال ، MongoDB یک فهرست جداگانه و کوچکتر را که فقط اشاره گر به محصولات موجود است ، حفظ می کند. MongoDB سپس می تواند از این ساختار برای یافتن سریعتر محصولات موجود در انبار استفاده کند.

در مراحل زیر ، یک پایگاه داده نمونه تهیه می کنید و از آن برای ایجاد فهرست های مختلف استفاده می کنید. شما خواهید آموخت که چگونه از صحت فهرست ها هنگام انجام پرس و جو استفاده کنید. درنهایت ، نحوه فهرست بندی فهرست های تعیین شده قبلی و حذف آنها را در صورت تمایل خواهید آموخت.

مرحله 1 – آماده سازی پایگاه داده نمونه

برای آشنایی با نحوه عملکرد نمایه ها و نحوه ایجاد آنها ، این مرحله نحوه بازکردن پوسته MongoDB را برای اتصال به نمونه MongoDB نصب شده در محلی توضیح می دهد. همچنین نحوه ایجاد مجموعه نمونه و درج چند نمونه نمونه در آن را توضیح می دهد. این راهنما از این نمونه داده ها برای نشان دادن انواع مختلف نمایه هایی که MongoDB می تواند برای بهبود عملکرد پرس و جو استفاده کند ، استفاده می کند.

برای ایجاد این مجموعه نمونه ، به پوسته MongoDB به عنوان کاربر مدیریتی خود متصل شوید. این آموزش از قوانین پیش نیاز آموزش امنیتی MongoDB پیروی می کند و فرض می کند که نام این کاربر مدیریتی AdminSammy و پایگاه داده احراز هویت آن admin است. اطمینان حاصل کنید که این جزئیات را در دستور زیر تغییر دهید تا در صورت متفاوت بودن تنظیمات خود را نشان دهد

mongo -u AdminSammy -p –authenticationDatabase admin

گذرواژه ای را که هنگام نصب برای دسترسی به پوسته تعیین کرده اید وارد کنید. پس از ارائه رمز عبور ، درخواست شما به علامت بزرگتر از (>) تغییر می کند.

برای نشان دادن نحوه عملکرد نمایه ها ، به مجموعه ای از اسناد با زمینه های مختلف از انواع مختلف نیاز داریم. ما از مجموعه نمونه پنج بلندترین کوه جهان استفاده خواهیم کرد. در زیر یک سند نمونه نشان دهنده قله اورست است:

The Everest document
{
    "name": "Everest",
    "height": 8848,
    "location": ["Nepal", "China"],
    "ascents": {
        "first": {
            "year": 1953,
        },
        "first_winter": {
            "year": 1980,
        },
        "total": 5656,
    }
}

این سند شامل اطلاعات زیر است:

  • name: نام قله
  • ارتفاع: ارتفاع قله ، بر حسب متر.
  • مکان: کشورهایی که کوه در آنها واقع شده است. این فیلد مقادیر را به عنوان یک آرایه ذخیره می کند تا کوه های واقع در بیش از یک کشور را مجاز کند.
  • صعودها: مقدار این فیلد سند دیگری است. هنگامی که یک سند در سند دیگری مانند این ذخیره می شود ، به عنوان یک سند جاسازی شده یا تو در تو شناخته می شود. هر سند صعود صعودهای موفقیت آمیز کوه داده شده را توصیف می کند. به طور خاص ، هر سند صعود شامل یک میدان کلی است که تعداد کل صعودهای موفق هر قله را نشان می دهد. علاوه بر این ، هر یک از این اسناد تو در تو دارای دو فیلد است که مقادیر آنها نیز اسناد تو در تو هستند:.
    • اول: ارزش این زمینه یک سند تو در تو است که شامل یک زمینه ، سال است ، که سال اولین صعود موفقیت آمیز کلی را توصیف می کند.
    • first_winter: مقدار این فیلد یک سند تو در تو است که شامل یک فیلد یک ساله نیز می شود ، که مقدار آن نشان دهنده سال اولین صعود زمستانی موفق به این کوه است.

روش insertMany () زیر را در پوسته MongoDB اجرا کنید تا همزمان مجموعه ای با نام peaks ایجاد کنید و پنج نمونه سند را در آن وارد کنید. این اسناد پنج بلندترین قله کوه در جهان را توصیف می کند:

db.peaks.insertMany([
{
“name”: “Everest”,
“height”: 8848,
“location”: [“Nepal”, “China”],
“ascents”: {
“first”: {
“year”: 1953
},
“first_winter”: {
“year”: 1980
},
“total”: 5656
}
},
{
“name”: “K2”,
“height”: 8611,
“location”: [“Pakistan”, “China”],
“ascents”: {
“first”: {
“year”: 1954
},
“first_winter”: {
“year”: 1921
},
“total”: 306
}
},
{
“name”: “Kangchenjunga”,
“height”: 8586,
“location”: [“Nepal”, “India”],
“ascents”: {
“first”: {
“year”: 1955
},
“first_winter”: {
“year”: 1986
},
“total”: 283
}
},
{
“name”: “Lhotse”,
“height”: 8516,
“location”: [“Nepal”, “China”],
“ascents”: {
“first”: {
“year”: 1956
},
“first_winter”: {
“year”: 1988
},
“total”: 461
}
},
{
“name”: “Makalu”,
“height”: 8485,
“location”: [“China”, “Nepal”],
“ascents”: {
“first”: {
“year”: 1955
},
“first_winter”: {
“year”: 2009
},
“total”: 361
}
}
])

خروجی شامل لیستی از شناسه های شی است که به اشیاء تازه وارد شده اختصاص داده شده است.

Output
{
        "acknowledged" : true,
        "insertedIds" : [
                ObjectId("61212a8300c8304536a86b2f"),
                ObjectId("61212a8300c8304536a86b30"),
                ObjectId("61212a8300c8304536a86b31"),
                ObjectId("61212a8300c8304536a86b32"),
                ObjectId("61212a8300c8304536a86b33")
        ]
}

با اجرای متد find () بدون آرگومان ، می توانید تأیید کنید که اسناد به درستی وارد شده اند ، که همه اسناد را بازیابی می کند

db.peaks.find()

Output
{ "_id" : ObjectId("61212a8300c8304536a86b2f"), "name" : "Everest", "height" : 8848, "location" : [ "Nepal", "China" ], "ascents" : { "first" : { "year" : 1953 }, "first_winter" : { "year" : 1980 }, "total" : 5656 } }

...

لطفاً توجه داشته باشید که این مجموعه نمونه آنقدر بزرگ نیست که بتواند تأثیر عملکرد شاخص ها یا فقدان آن را مستقیماً نشان دهد. با این حال ، این راهنما نحوه استفاده MongoDB از ایندکس ها را برای محدود کردن میزان اسناد مرور شده با توجه به جزئیات پرس و جو که توسط موتور پایگاه داده گزارش شده است ، توضیح می دهد.

با استفاده از داده های نمونه ، می توانید به مرحله بعدی ادامه دهید تا نحوه ایجاد فهرست بر اساس یک زمینه را بیاموزید.

مرحله 2 – ایجاد یک فهرست واحد و ارزیابی استفاده از شاخص

این مرحله نحوه ایجاد یک فهرست زمینه واحد را برای سرعت بخشیدن به درخواست های سند که داده ها را با استفاده از آن فیلتر به عنوان بخشی از شرایط فیلترینگ فیلتر می کند ، توضیح می دهد. همچنین نحوه تأیید اینکه آیا MongoDB از شاخصی برای افزایش عملکرد پرس و جو استفاده کرده است یا به جای آن به اسکن مجموعه کامل متوسل شده است ، اشاره می کند.

برای شروع ، عبارت زیر را اجرا کنید. به طور معمول ، سند پرس و جو {“height”: {$ gt: 8700}} باعث می شود که این پرس و جو هرگونه اسنادی را که قله کوهی با ارزش ارتفاع بیش از 8700 توصیف می کند ، بازیابی کند. با این حال ، این عملیات شامل روش توضیح (executiveStats) ، که باعث می شود پرس و جو در عوض اطلاعات مربوط به نحوه انجام این پرس و جو را برگرداند. از آنجا که هنوز هیچ نمایه ای ایجاد نکرده اید ، این یک معیار در اختیار شما قرار می دهد که می توانید از آن برای مقایسه در برابر پرس و جوهایی که از نمایه استفاده می کنند استفاده کنید:

db.peaks.find(
{ “height”: { $gt: 8700 } }
).explain(“executionStats”)

این عملیات اطلاعات زیادی را برمی گرداند. خروجی مثال زیر تعدادی خط را حذف می کند که برای اهداف این آموزش مهم نیستند:

Output
{
        "queryPlanner" : {
                . . .
                "winningPlan" : {
                        "stage" : "COLLSCAN",
                        . . .
                },
        },
        . . .
        "executionStats" : {
                . . .
                "nReturned" : 1,
                "executionTimeMillis" : 0,
                "totalKeysExamined" : 0,
                "totalDocsExamined" : 5,
                . . .
        },
        . . .
}

زمینه های زیر که در این خروجی بازگردانده می شوند به طور خاص برای درک نحوه عملکرد نمایه ها مرتبط هستند:

WinPlan: این سند در بخش queryPlanner نحوه تصمیم گیری MongoDB برای اجرای پرس و جو را توضیح می دهد. بسته به نوع پرس و جو ، ساختار دقیق طرح برنده ممکن است متفاوت باشد ، اما در اینجا نکته اصلی که باید به آن توجه کنید COLLSCAN است. وجود این مقدار بدین معناست که MongoDB برای یافتن اسناد درخواستی نیاز به گذراندن مجموعه کامل بدون هیچ گونه کمکی داشت.
n بازگردانده شده: این مقدار به شما می گوید که چند سند توسط یک پرس و جو معین برگردانده شده است. در اینجا ، فقط یک قله کوه با پرس و جو مطابقت دارد.
ExeTimeMillis: این مقدار نشان دهنده زمان اجرا است. با چنین مجموعه کوچکی ، اهمیت آن ناچیز است. با این حال ، هنگام تجزیه و تحلیل عملکرد پرس و جوها در برابر مجموعه های بزرگتر یا پیچیده تر ، باید معیار مهمی را در نظر داشت.
totalKeysExamined: این به شما می گوید که چند مدخل فهرست را برای پیدا کردن اسناد درخواست شده در MongoDB بررسی کرده است. از آنجا که از اسکن مجموعه استفاده شد و شما هنوز هیچ فهرست ایجاد نکرده اید ، مقدار 0 است.
totalDocsExamined: این مقدار نشان می دهد که چند سند باید MongoDB از مجموعه بخواند. از آنجا که MongoDB یک اسکن مجموعه انجام داد ، مقدار آن 5 ، تعداد کل اسناد موجود در مجموعه است. هرچه مجموعه بزرگتر باشد ، در صورت عدم استفاده از نمایه ها ، مقدار بیشتری در این زمینه وجود دارد.
به تفاوت بین کل اسناد مورد بررسی و تعداد اسناد برگشت داده شده توجه کنید: MongoDB مجبور شد 5 سند را برای بازگرداندن یک سند بازرسی کند.

این آموزش در بخشهای بعدی به این مقادیر اشاره می کند تا نحوه تأثیر نمایه ها بر نحوه اجرای پرس و جوها را تجزیه و تحلیل کند.

برای این منظور ، با استفاده از متد createIndex () ، یک شاخص در قسمت height در مجموعه peaks ایجاد کنید. این روش یک سند JSON را توصیف می کند که نمایه ای را که می خواهید ایجاد کنید توصیف می کند. این مثال یک فهرست زمینه واحد ایجاد می کند ، به این معنی که سند حاوی یک کلید واحد (ارتفاع در این مثال) برای فیلدی است که می خواهیم از آن استفاده کنیم. این کلید 1 یا -1 را به عنوان مقدار می پذیرد. این مقادیر ترتیب مرتب سازی شاخص را نشان می دهند که 1 نشان دهنده صعودی و -1 نشان دهنده نزولی است:

db.peaks.createIndex( { “height”: 1 } )

MongoDB تأییدی را برمی گرداند که نشان می دهد چند شاخص در حال حاضر در مجموعه تعریف شده است و تفاوت آن با حالت قبلی.

Output

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

حالا سعی کنید همان پرس و جو را که قبلاً اجرا کرده اید اجرا کنید. هرچند این بار ، اطلاعاتی که با روش توضیح (“exeStatStats”) بازگردانده می شوند ، متفاوت است زیرا نمایه ای در محل وجود دارد:

db.peaks.find(
{ “height”: { $gt: 8700 } }
).explain(“executionStats”)

Output
{
        "queryPlanner" : {
                . . .
                "winningPlan" : {
                        . . .
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                . . .
                                "indexName" : "height_1",
                                . . .
                        }
                },
                . . .
        },
        "executionStats" : {
                . . .
                "nReturned" : 1,
                "executionTimeMillis" : 0,
                "totalKeysExamined" : 1,
                "totalDocsExamined" : 1,
                . . .
        },
        . . .
}

توجه کنید که WinPlan دیگر COLLSCAN را نشان نمی دهد. در عوض ، IXSCAN وجود دارد ، نشان می دهد که از ایندکس به عنوان بخشی از اجرای پرس و جو استفاده شده است. MongoDB همچنین به شما اطلاع می دهد که کدام شاخص از طریق مقدار indexName استفاده شده است. به طور پیش فرض ، MongoDB نامهای فهرست را از نامهای فیلدی که فهرست به آنها متصل است و ترتیب اعمال می شود ، می سازد. از {“height”: 1} ، MongoDB به طور خودکار نام height_1 را ایجاد کرد.

مهمترین تغییر در بخش exeStats است. یکبار دیگر ، این پرس و جو فقط یک سند واحد را که با nReturned مشخص شده است ، باز می گرداند. با این حال ، این بار totalDocsExamined فقط 1 است. این بدان معناست که پایگاه داده فقط یک سند را از مجموعه بازیابی کرده تا پرس و جو را برآورده کند. TotalKeysExamined نشان می دهد که شاخص فقط یک بار بررسی شده است زیرا اطلاعات کافی برای جمع آوری نتیجه را ارائه می دهد.

با ایجاد این فهرست ، تعداد اسنادی را که MongoDB مجبور به بازرسی بود ، از 5 به 1 کاهش دادید ، که پنج برابر کاهش می یابد. اگر مجموعه قله ها حاوی هزاران مدخل باشد ، تأثیر استفاده از شاخص حتی بیشتر آشکار می شود.

مرحله 3 – ایجاد نمایه های منحصر به فرد

در MongoDB ، درج دو سند در مجموعه اگر هر دو دارای مقادیر _id یکسانی باشند ، غیرممکن است. این به این دلیل است که پایگاه داده به طور خودکار یک فهرست تک فیلدی در قسمت _id حفظ می کند که علاوه بر کمک به سرعت بخشیدن به جستجوی اسناد ، منحصر به فرد بودن مقدار فیلد _id را تضمین می کند. این مرحله توضیح می دهد که چگونه می توانید فهرست بندی کنید تا مطمئن شوید مقادیر یک فیلد معین برای هر سند در یک مجموعه منحصر به فرد است.

برای توضیح ، روش createIndex () زیر را اجرا کنید. نحو این دستور مشابه آنچه در مرحله قبل استفاده شد است ، با این تفاوت که این بار یک پارامتر دوم با ایجاد تنظیمات اضافی برای index () به createIndex () منتقل می شود. {“منحصر به فرد”: true} نشان می دهد که شاخص ایجاد شده اطمینان می دهد که مقادیر فیلد (نام) مشخص شده نمی تواند تکرار شود:

db.peaks.createIndex( { “name”: 1 }, { “unique”: true } )

بار دیگر ، MongoDB تأیید می کند که این فهرست با موفقیت ایجاد شده است:

Output
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 2,
        "numIndexesAfter" : 3,
        "ok" : 1
}

در مرحله بعد ، بررسی کنید که آیا ایندکس به منظور اصلی خود عمل می کند یا با اجتناب از اسکن مجموعه ، هر گونه پرس و جو را سریعتر با نام کوه اجرا می کند. برای انجام این کار ، عبارت برابری زیر را با روش توضیحی (“executiveStats”) اجرا کنید:

db.peaks.find(
{ “name”: “Everest” }
).explain(“executionStats”)

طرح پرس و جو بازگشتی از استراتژی IXSCAN با شاخص تازه ایجاد شده استفاده می کند ، درست مانند پرس و جو ارتفاع کوه از مرحله قبل:

Output
{
        "queryPlanner" : {
                . . .
                "winningPlan" : {
                        . . .
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                . . .
                                "indexName" : "name_1",
                                . . .
                        }
                },
                . . .
        },
        . . .
}

در مرحله بعد بررسی کنید که آیا می توانید سند دیگری را که نمایانگر کوه اورست است به مجموعه اضافه کنید ، در حالی که فهرست در جای خود قرار دارد. این کار را با اجرای روش insertOne () زیر انجام دهید:

db.peaks.insertOne({
“name”: “Everest”,
“height”: 9200,
“location”: [“India”],
“ascents”: {
“first”: {
“year”: 2020
},
“first_winter”: {
“year”: 2021
},
“total”: 2
}
})

MongoDB سند را ایجاد نمی کند و در عوض پیغام خطا را برمی گرداند:

Output
WriteError({
        "index" : 0,
        "code" : 11000,
        "errmsg" : "E11000 duplicate key error collection: test.peaks index: name_1 dup key: { name: \"Everest\" }",
        "op" : {
            . . .

این پیام خطای کلید duplicatye به فهرست name_1 اشاره دارد ، نشان می دهد که این محدودیت منحصر به فرد را در این زمینه اعمال می کند.

با این کار ، شما آموخته اید که چگونه یک فهرست منحصر به فرد ایجاد کنید تا از فیلدهای معین حاوی مقادیر تکراری جلوگیری شود. برای یادگیری نحوه استفاده از نمایه ها با اسناد تعبیه شده ، به خواندن ادامه دهید.

مرحله 4 – ایجاد یک فهرست در یک میدان جاسازی شده

هر زمان که از مجموعه ای با استفاده از فیلدی در سند تو در تو که نمایه ای ندارد ، درخواست می کنید ، MongoDB نه تنها باید همه اسناد را از مجموعه بازیابی کند ، بلکه باید از هر سند تو در تو نیز عبور کند.

به عنوان مثال ، عبارت زیر را اجرا کنید. با این کار اسنادی که مجموع آنها – فیلدی که درون سند صعودهای موجود در هر سند در مجموعه قله ها قرار گرفته است – بیش از 300 است و نتایج را به ترتیب نزولی مرتب می کند:

db.peaks.find(
{ “ascents.total”: { $gt: 300 } }
).sort({ “ascents.total”: -1 })

این پرس و جو چهار قله از مجموعه را باز می گرداند ، با کوه اورست قله با بیشترین صعود ، و پس از آن Lhotse ، Makalu و K2:

Output
{ "_id" : ObjectId("61212a8300c8304536a86b2f"), "name" : "Everest", "height" : 8848, "location" : [ "Nepal", "China" ], "ascents" : { "first" : { "year" : 1953 }, "first_winter" : { "year" : 1980 }, "total" : 5656 } }
{ "_id" : ObjectId("61212a8300c8304536a86b32"), "name" : "Lhotse", "height" : 8516, "location" : [ "Nepal", "China" ], "ascents" : { "first" : { "year" : 1956 }, "first_winter" : { "year" : 1988 }, "total" : 461 } }
{ "_id" : ObjectId("61212a8300c8304536a86b33"), "name" : "Makalu", "height" : 8485, "location" : [ "China", "Nepal" ], "ascents" : { "first" : { "year" : 1955 }, "first_winter" : { "year" : 2009 }, "total" : 361 } }
{ "_id" : ObjectId("61212a8300c8304536a86b30"), "name" : "K2", "height" : 8611, "location" : [ "Pakistan", "China" ], "ascents" : { "first" : { "year" : 1954 }, "first_winter" : { "year" : 1921 }, "total" : 306 } }

اکنون همان پرس و جو را اجرا کنید ، اما روش توضیح ((exeStatStats)) را که قبلاً استفاده شده بود ، وارد کنید:

db.peaks.find(
{ “ascents.total”: { $gt: 300 } }
).sort({ “ascents.total”: -1 }).explain(“executionStats”)

همانطور که مقدار COLLSCAN در این بخش از خروجی نشان می دهد ، MongoDB به یک اسکن مجموعه کامل متوسل شد و تمام اسناد مجموعه peaks را مرور کرد تا آنها را با شرایط پرس و جو مقایسه کند:

Output
{
        . . .
                "winningPlan" : {
                        "stage" : "COLLSCAN",
                        . . .
                },
        . . .
}

از آنجا که این مجموعه فقط پنج مدخل دارد ، فقدان شاخص تأثیر چندانی بر عملکرد نداشت و این پرس و جو بلافاصله اجرا شد. با این حال ، هرچه اسناد ذخیره شده در پایگاه داده پیچیده تر باشد ، پرس و جوهای تاثیرگذاری عملکرد بیشتری می تواند داشته باشد. این مرحله نحوه ایجاد نمایه های تک زمینه در زمینه های داخل اسناد تعبیه شده را برای کمک به کاهش این مشکل نشان می دهد.

برای کمک به MongoDB در اجرای این پرس و جو ، بیایید یک فهرست در قسمت کل در سند صعودها ایجاد کنیم. از آنجا که کل میدان درون صعودها قرار گرفته است ، هنگام ایجاد این فهرست نمی توان کل را به عنوان نام فیلد مشخص کرد. در عوض ، MongoDB یک نماد نقطه برای دسترسی به فیلدها در اسناد تو در تو ارائه می دهد. برای ارجاع به فیلد کل داخل سند صعودی ، می توانید از علامت ascents.total ، مانند این استفاده کنید:

db.peaks.createIndex( { “ascents.total”: 1 } )

MongoDB با پیام موفقیت آمیز پاسخ می دهد که به شما اطلاع می دهد که اکنون چهار فهرست تعریف شده دارید.

{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 3,
        "numIndexesAfter" : 4,
        "ok" : 1
}

پرس و جو قبلی را یکبار دیگر اجرا کنید تا بررسی کنید که آیا این فهرست به MongoDB کمک کرده است تا از اسکن کامل مجموعه جلوگیری کند:

db.peaks.find(
{ “ascents.total”: { $gt: 300 } }
).sort({ “ascents.total”: -1 }).explain(“executionStats”)

Output
{
        "queryPlanner" : {
                . . .
                "winningPlan" : {
                        . . .
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                . . .
                                "indexName" : "ascents.total_-1",
                                . . .
                        }
                },
                . . .
        },
        "executionStats" : {
                . . .
                "nReturned" : 4,
                "executionTimeMillis" : 0,
                "totalKeysExamined" : 4,
                "totalDocsExamined" : 4,
                . . .
                "direction" : "backward",
                . . .
        },
        . . .
}

توجه داشته باشید که در حال حاضر IXSCAN در برابر شاخص تازه ایجاد شده ascents.total_-1 استفاده می شود و فقط چهار سند مورد بررسی قرار گرفته است. این همان تعداد اسنادی است که در فهرست بازگردانده شده و بررسی شده اند ، بنابراین هیچ سند دیگری برای تکمیل پرس و جو بازیابی نشده است.

جهت ، یک فیلد دیگر در بخش ExeStats ، نشان می دهد که MongoDB در کدام جهت تصمیم گرفته است که از ایندکس عبور کند. از آنجا که این شاخص با استفاده از نحو {“ascents.total”: 1} ایجاد صعودی شد و پرس و جو قله های کوه را به ترتیب نزولی مرتب کرد ، موتور پایگاه داده تصمیم گرفت به عقب برگردد. هنگام بازیابی اسناد به ترتیب خاص بر اساس فیلدی که بخشی از فهرست است ، MongoDB از فهرست برای ارائه سفارش نهایی بدون نیاز به مرتب سازی بیشتر اسناد پس از بازیابی کامل آنها استفاده می کند.

مرحله 5 – ایجاد Compound Field Index

مثالهای تا کنون در این راهنما برای درک مزایای استفاده از نمایه ها مفید است ، اما پرسشهای فیلترینگ سند مورد استفاده در برنامه های دنیای واقعی به ندرت به این سادگی است. این مرحله توضیح می دهد که چگونه MongoDB از نمایه ها هنگام اجرای پرس و جو در بیش از یک زمینه استفاده می کند و نحوه استفاده از نمایه های مرکب برای هدف قرار دادن چنین پرس و جوهایی به طور خاص.

هنگامی که یک فهرست میدان واحد در زمینه ارتفاع ایجاد کردید ، از مرحله 2 به یاد بیاورید تا به طور م moreثرتری از مجموعه قله ها برای یافتن بلندترین قله های کوه جستجو کنید. با استفاده از این شاخص ، بیایید تجزیه و تحلیل کنیم که چگونه MongoDB یک پرس و جو مشابه اما کمی پیچیده تر را انجام می دهد. سعی کنید کوه هایی با ارتفاع کمتر از 8600 متر پیدا کنید که اولین صعود زمستانی آنها پس از سال 1990 رخ داده است:

db.peaks.find(
{
“ascents.first_winter.year”: { $gt: 1990 },
“height”: { $lt: 8600 }
}
).sort({ “height”: -1 })

فقط یک کوه واحد – ماکالو – هر دو شرایط زیر را برآورده می کند:

Output
{ "_id" : ObjectId("61212a8300c8304536a86b33"), "name" : "Makalu", "height" : 8485, "location" : [ "China", "Nepal" ], "ascents" : { "first" : { "year" : 1955 }, "first_winter" : { "year" : 2009 }, "total" : 361 } }

حالا روش توضیح (“executiveStats”) را اضافه کنید تا نحوه انجام این درخواست توسط MongoDB را بیابید:

db.peaks.find(
{
“ascents.first_winter.year”: { $gt: 1990 },
“height”: { $lt: 8600 }
}
).sort({ “height”: -1 }).explain(“executionStats”)

حتی اگر هیچ شاخصی وجود نداشته باشد که ممکن است بر اولین صعود زمستانی تأثیر بگذارد ، MongoDB به جای انجام یک اسکن کامل مجموعه ، از یک شاخص ایجاد شده قبلی استفاده کرد:

Output
{
        "queryPlanner" : {
                . . .
                "winningPlan" : {
                                "stage" : "IXSCAN",
                                . . .
                                "indexName" : "height_1",
                                . . .
                        }
                },
                . . .
        },
        "executionStats" : {
                . . .
                "nReturned" : 1,
                "executionTimeMillis" : 0,
                "totalKeysExamined" : 3,
                "totalDocsExamined" : 3,
                . . .
        },
        . . .
}

توجه کنید که این بار ، متفاوت از اعدامهای پرس و جو با نمایه قبلی ، مقدار nReturned که تعداد اسناد برگشتی را نشان می دهد متفاوت از totalKeysExamined و totalDocsExamined است. MongoDB از شاخص میدان واحد در زمینه ارتفاع برای محدود کردن نتایج از 5 به 3 استفاده کرد ، اما سپس مجبور شد اسناد باقی مانده را برای بررسی اولین تاریخ صعود زمستانی اسکن کند.

اگر یک فهرست فقط برای یک قسمت از یک پرس و جو در دسترس باشد ، MongoDB از آن برای محدود کردن نتایج ابتدا قبل از انجام اسکن مجموعه استفاده می کند. این برنامه فقط لیست اسنادی را که ابتدا فیلتر کرده است را برآورده می کند تا بقیه پرس و جو را برآورده کند.

در بسیاری از موارد ، این کاملاً کافی است. اگر متداول ترین پرس و جوها یک فیلد نمایه شده را بررسی می کنند و فقط گاهی اوقات باید فیلتر اضافی انجام دهند ، داشتن یک فهرست زمینه واحد معمولاً به اندازه کافی خوب است. هرچند که پرس و جوها در زمینه های متعدد متداول هستند ، ممکن است مفید باشد که یک فهرست شامل همه این زمینه ها مشخص شود تا مطمئن شوید هیچ اسکن اضافی نباید انجام شود.

تصور کنید که پایگاه داده قله های کوه را مطابق شرایط مطلوب مربوط به اولین صعود و ارتفاع زمستانی آنها به طور منظم جستجو کنید تا به نگرانی عملکرد تبدیل شود و از داشتن یک فهرست سودمند باشد. برای ایجاد یک فهرست بر اساس هر دو زمینه ، روش createIndex (0) زیر را اجرا کنید:

db.peaks.createIndex(
{
“ascents.first_winter.year”: 1,
“height”: -1
}
)

توجه کنید که نحو این عملیات مشابه ایجاد نمایه میدان واحد است ، اما این بار هر دو فیلد در شی تعریف شاخص فهرست شده اند. این شاخص با توجه به اولین صعودهای زمستانی قله ها و با توجه به ارتفاعات آنها صعودی ایجاد می شود.

MongoDB تصدیق می کند که این فهرست با موفقیت ایجاد شده است:

Output
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 4,
        "numIndexesAfter" : 5,
        "ok" : 1
}

با نمایه های تک زمینه ای ، موتور پایگاه داده می تواند آزادانه از شاخص به جلو یا عقب عبور کند. با این حال ، در مورد شاخص های ترکیبی این همیشه صادق نیست. اگر دستور مرتب سازی خاصی برای ترکیبی از زمینه ها بیشتر مورد پرس و جو قرار گیرد ، می تواند عملکرد را افزایش دهد و آن ترتیب را در تعریف فهرست لحاظ کند. MongoDB سپس سفارش درخواستی را با استفاده از ایندکس مستقیماً برآورده می کند ، نه اینکه مرتب سازی بیشتری در لیست اسناد برگشتی انجام دهد.

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

db.peaks.find(
{
“ascents.first_winter.year”: { $gt: 1990 },
“height”: { $lt: 8600 }
}
).sort({ “height”: -1 }).explain(“executionStats”)

این بار پرس و جو دوباره از اسکن فهرست استفاده کرد ، اما شاخص متفاوت است. اکنون ، شاخص ascents.first_winter.year_1_height_-1 که به تازگی ایجاد کرده اید ، بر روی شاخص height_1 که قبلاً استفاده شده بود ، انتخاب می شود:

Output
{
        "queryPlanner" : {
                . . .
                "winningPlan" : {
                                "stage" : "IXSCAN",
                                . . .
                                "indexName" : "ascents.first_winter.year_1_height_-1",
                                . . .
                        }
                },
                . . .
        },
        "executionStats" : {
                . . .
                "nReturned" : 1,
                "executionTimeMillis" : 0,
                "totalKeysExamined" : 1,
                "totalDocsExamined" : 1,
                . . .
        },
        . . .
}

تفاوت مهم در exeStats نهفته است. با نمایه جدید ، یک سند واحد مستقیماً از فهرست مورد بررسی قرار گرفت و سپس بازگردانده شد ، در مقابل سه سند که برای محدود کردن نتایج به اسکن بیشتر سند نیاز داشتند. اگر این مجموعه بزرگتر بود ، تفاوت بین شاخص مرکب جدید و استفاده از یک فهرست میدان واحد با فیلتر بیشتر حتی بیشتر نمایان می شد.

اکنون که نحوه ایجاد فهرست هایی را که شامل بیش از یک زمینه می شود یاد گرفته اید ، می توانید به سراغ یادگیری نمایه های چند کلیدی و نحوه استفاده از آنها بروید.

مرحله 6-ایجاد یک فهرست چند کلیدی

در مثالهای قبلی ، فیلدهای مورد استفاده در فهرستها دارای مقادیر واحد مانند قد ، یک سال یا یک نام در آنها بود. در این موارد ، MongoDB مقدار میدان را مستقیماً به عنوان کلید فهرست ذخیره می کند ، و این شاخص را به سرعت قابل عبور می کند. این مرحله نحوه رفتار MongoDB را نشان می دهد وقتی فیلدی که برای ایجاد ایندکس استفاده می شود ، فیلدی است که مقادیر متعددی مانند آرایه را ذخیره می کند.

برای شروع ، سعی کنید تمام کوه های موجود در مجموعه ای را که در نپال واقع شده اند پیدا کنید:

db.peaks.find(
{ “location”: “Nepal” }
)

چهار قله باز می گردند:

Output
{ "_id" : ObjectId("61212a8300c8304536a86b2f"), "name" : "Everest", "height" : 8848, "location" : [ "Nepal", "China" ], "ascents" : { "first" : { "year" : 1953 }, "first_winter" : { "year" : 1980 }, "total" : 5656 } }
{ "_id" : ObjectId("61212a8300c8304536a86b31"), "name" : "Kangchenjunga", "height" : 8586, "location" : [ "Nepal", "India" ], "ascents" : { "first" : { "year" : 1955 }, "first_winter" : { "year" : 1986 }, "total" : 283 } }
{ "_id" : ObjectId("61212a8300c8304536a86b32"), "name" : "Lhotse", "height" : 8516, "location" : [ "Nepal", "China" ], "ascents" : { "first" : { "year" : 1956 }, "first_winter" : { "year" : 1988 }, "total" : 461 } }
{ "_id" : ObjectId("61212a8300c8304536a86b33"), "name" : "Makalu", "height" : 8485, "location" : [ "China", "Nepal" ], "ascents" : { "first" : { "year" : 1955 }, "first_winter" : { "year" : 2009 }, "total" : 361 } }

توجه داشته باشید که هیچ یک از این قله ها فقط در نپال نیستند. هر یک از این چهار قله دارای بیش از یک کشور هستند که توسط فیلدهای مکان آنها مشخص شده است ، که همه آنها مجموعه ای از مقادیر متعدد هستند. علاوه بر این ، این مقادیر می توانند به ترتیب مختلف ظاهر شوند. به عنوان مثال ، لوتسه در [[نپال] ، \ “چین]] ، در حالی که ماکالو در [” چین “،” نپال “] ذکر شده است.

از آنجا که هیچ فهرست موجود در زمینه مکان وجود ندارد ، MongoDB در حال حاضر یک اسکن مجموعه کامل برای اجرای آن پرس و جو انجام می دهد. بیایید یک فهرست جدید برای قسمت مکان ایجاد کنیم:

db.peaks.createIndex( { “location”: 1 } )

توجه داشته باشید که این نحو با هیچ نمای میدان دیگری متفاوت نیست. MongoDB پیام موفقیت را برمی گرداند و ایندکس اکنون برای استفاده در دسترس است:

Output
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 5,
        "numIndexesAfter" : 6,
        "ok" : 1
}

اکنون که یک فهرست برای قسمت مکان ایجاد کرده اید ، پرس و جوی قبلی را مجدداً با متد توضیح (“exeStatStats”) اجرا کنید تا نحوه اجرای آن را درک کنید:

db.peaks.find(
{ “location”: “Nepal” }
).explain(“executionStats”)

خروجی حاصله نشان می دهد که MongoDB از اسکن فهرست بعنوان استراتژی استفاده کرده است و با اشاره به نمای جدید location_1 ایجاد شده است:

Output
{
        "queryPlanner" : {
                . . .
                "winningPlan" : {
                        . . .
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                . . .
                                "indexName" : "location_1",
                                "isMultiKey" : true,
                                . . .
                        }
                },
                . . .
        },
        "executionStats" : {
                . . .
                "nReturned" : 4,
                "executionTimeMillis" : 0,
                "totalKeysExamined" : 4,
                "totalDocsExamined" : 4,
                . . .
        }
        . . .
}

تعداد اسناد برگشتی با تعداد کل کلیدهای مورد بررسی و اسناد مورد بررسی مطابقت دارد. این بدان معناست که ایندکس به عنوان تنها منبع اطلاعات برای پرس و جو مورد استفاده قرار گرفت. چگونه ممکن است اگر مقادیر میدان دارای آرایه های بیش از یک مقدار باشند و در درخواست از کوههایی با یکی از مکان های منطبق با نپال خواسته شود؟

به ویژگی isMultiKey که در خروجی true ذکر شده توجه کنید. MongoDB به طور خودکار یک فهرست چند کلیدی برای قسمت مکان ایجاد کرد. اگر یک فهرست برای آرایه های دارای فیلد ایجاد کنید ، MongoDB به طور خودکار تعیین می کند که باید یک فهرست چند کلیدی ایجاد کند و برای هر عنصر از این آرایه ها ورودی های شاخص جداگانه ایجاد می کند.

بنابراین ، برای سندی که دارای فیلد مکان ذخیره آرایه [“چین” ، “نپال”] است ، دو ورودی فهرست جداگانه برای یک سند ، یکی برای چین و دیگری برای نپال ظاهر می شود. به این ترتیب ، MongoDB می تواند از ایندکس به نحو احسن استفاده کند ، حتی اگر query درخواست تطابق جزئی با محتویات آرایه را داشته باشد.

مرحله 7 – فهرست بندی و حذف فهرستها در یک مجموعه

در مراحل قبل ، نحوه ایجاد انواع مختلف فهرست ها را آموخته اید. هنگامی که پایگاه داده رشد می کند یا الزامات تغییر می کند ، مهم است که بتوانید بدانید چه شاخص هایی تعریف شده اند و گاهی اوقات موارد ناخواسته را حذف می کنید. ایندکس هایی که دیگر مفید نیستند می توانند تأثیر منفی بر عملکرد پایگاه داده داشته باشند ، زیرا MongoDB همچنان باید در هر زمان که داده ها را اضافه یا تغییر می دهید ، آنها را حفظ کند.

برای فهرست بندی تمام نمایه هایی که در مجموعه آموزش در این مجموعه آموزشی تعریف کرده اید ، می توانید از روش getIndexes () استفاده کنید:

db.peaks.getIndexes()

MongoDB فهرست فهرست ها را باز می گرداند ، ماهیت آنها را شرح می دهد و نام آنها را فهرست می کند:

Output
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_"
        },
        {
                "v" : 2,
                "key" : {
                        "height" : 1
                },
                "name" : "height_1"
        },
        {
                "v" : 2,
                "unique" : true,
                "key" : {
                        "name" : 1
                },
                "name" : "name_1"
        },
        {
                "v" : 2,
                "key" : {
                        "ascents.total" : 1
                },
                "name" : "ascents.total_1"
        },
        {
                "v" : 2,
                "key" : {
                        "ascents.first_winter.year" : 1,
                        "height" : -1
                },
                "name" : "ascents.first_winter.year_1_height_-1"
        },
        {
                "v" : 2,
                "key" : {
                        "location" : 1
                },
                "name" : "location_1"
        }
]

در طول این آموزش ، شما به طور کلی 6 نمایه را تعریف کرده اید. برای هر یک ، ویژگی کلیدی فهرست شاخص را فهرست می کند ، مطابق با نحوه ایجاد شاخص قبل است. برای هر فهرست ، ویژگی نام شامل نام MongoDB است که به طور خودکار هنگام ایجاد فهرست ایجاد می شود.

برای حذف یک فهرست موجود ، می توانید از هر یک از این ویژگی ها با روش dropIndex () استفاده کنید. مثال زیر با استفاده از تعریف محتویات ، شاخص height_1 را حذف می کند:

db.peaks.dropIndex( { “height”: 1 } )

از آنجا که {“height”: 1} با نمای زمینه واحد در ارتفاع به نام height_1 مطابقت دارد ، MongoDB آن فهرست را حذف کرده و با پیامی موفقیت آمیز نشان می دهد که چند شاخص قبل از حذف این مورد وجود داشت:

Output
{ "nIndexesWas" : 6, "ok" : 1 }

این روش تعیین شاخص برای حذف می تواند در صورت پیچیده تر بودن تعریف شاخص ، مانند آنچه که در مورد نمایه های مرکب اتفاق می افتد ، دشوار باشد. به عنوان جایگزین ، می توانید فهرست ها را با استفاده از نام فهرست حذف کنید. برای حذف شاخص ایجاد شده در اولین صعود و ارتفاع زمستانی در مرحله 5 با استفاده از نام آن ، عملیات زیر را اجرا کنید:

db.peaks.dropIndex(“ascents.first_winter.year_1_height_-1”)

بار دیگر ، MongoDB فهرست را حذف کرده و یک پیام موفقیت آمیز نشان می دهد:

Output
{ "nIndexesWas" : 5, "ok" : 1 }

با فراخوانی مجدد getIndexes () می توانید تأیید کنید که این دو فهرست در واقع از لیست فهرست مجموعه حذف شده اند:

db.peaks.getIndexes()

این بار ، تنها چهار فهرست باقی مانده فهرست شده است:

Output
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_"
        },
        {
                "v" : 2,
                "unique" : true,
                "key" : {
                        "name" : 1
                },
                "name" : "name_1"
        },
        {
                "v" : 2,
                "key" : {
                        "ascents.total" : 1
                },
                "name" : "ascents.total_1"
        },
        {
                "v" : 2,
                "key" : {
                        "location" : 1
                },
                "name" : "location_1"
        }
]

به عنوان آخرین نکته ، توجه داشته باشید که امکان تغییر فهرست موجود در MongoDB وجود ندارد. اگر نیاز به تغییر یک فهرست دارید ، ابتدا باید آن فهرست را رها کرده و یک فهرست جدید ایجاد کنید.

نتیجه

با خواندن این مقاله ، شما با مفهوم نمایه ها آشنا شده اید – ساختارهای داده خاصی که می توانند با کاهش میزان داده هایی که MongoDB باید در طول اجرای پرس و جو تجزیه و تحلیل کند ، عملکرد پرس و جو را بهبود بخشد. شما آموخته اید که چگونه فهرست های تک زمینه ای ، مرکب و چند کلیدی ایجاد کنید ، و همچنین چگونه بررسی کنید که آیا وجود آنها بر اجرای پرس و جو تأثیر می گذارد یا خیر. شما همچنین یاد گرفته اید که چگونه فهرست های موجود را لیست کرده و موارد ناخواسته را حذف کنید.

 


سرور مجازی آلمان

سرور مجازی آمریکا

سرور مجازی فرانسه

سرور مجازی کانادا

سرور مجازی لهستان

سرور مجازی هلند

سرور مجازی انگلیس

برچسب‌ها:, , , ,