ادغام روابط reference با lookUp در MongoDB

Integrate Reference Relationships with lookUp in MongoDB

06 بهمن 1400
درسنامه درس 20 از سری دوره جامع آموزش MongoDB
MongoDB: ادغام روابط reference با lookUp (قسمت 20)

در این قسمت می خواهیم در رابطه با متدی صحبت کنیم که به شما اجازه می دهد document های مرتبط از طریق reference ها را در هم ادغام کنید. این متد که متد lookUp است یکی از کاربردی ترین متد های ما می باشد چرا که در بسیاری از اوقات پایگاه داده را با reference ها طراحی می کنیم اما بعدا پشیمان می شویم و می خواهیم از embedded document ها استفاده کنیم.

ما در جلسه قبل دو collection به نام های authors و books داشتیم که books به شکل زیر بود:

        "_id" : ObjectId("5e8882355159280df164b054"),
        "name" : "My favorite Book",
        "authors" : [
                ObjectId("5e8882d85159280df164b055"),
                ObjectId("5e8882d85159280df164b056")
        ]
}

همانطور که مشخص است ما در اینجا از reference ها استفاده کرده ایم. حالا فرض کنید که می خواهیم کتاب ها را به همراه اطلاعات نویسنده ها و نه id هایشان دریافت کنم. برای این کار باید از متد aggregate (به معنی «جمع کردن» یا «اجتماع») استفاده کنیم. ما هنوز در مورد این متد چیزی نگفته ایم و من هم نمی خواهم این جلسه را به متد aggregate اختصاص بدهم (در فصل های آینده به طور مفصل آن را بررسی می کنیم). فعلا این قسمت را نادیده بگیرید. برای ادغام اطلاعات نویسنده ها و کتاب ها و دریافت آن ها به صورت یکجا می گوییم:

db.books.aggregate([{$lookup: {from: "authors", localField: "authors", foreignField: "_id", as: "creators"}}]).pretty()

همانطور که می بینید باید یک آرایه را به متد aggregate پاس بدهیم. سپس هر document یک «مرحله» به حساب می آید و از آنجایی که کار ما فقط یک مرحله است من فقط یک document را درون این آرایه تعریف کرده ام. سپس باید lookup$ را نوشته و به عنوان مقدار، یک document را پاس بدهید. یادتان باشد که ما می خواهیم اطلاعات دو collection را در هم ادغام کنیم بنابراین باید مشخص کنیم کدام اطلاعات و کدام collection ها. این موضوع کار lookup است و شامل چهار فیلد اصلی است:

  • From یعنی از کدام collection دیگر باید داده ها را اضافه کنم؟ ما متد aggregate را روی books صدا زده ایم بنابراین اطلاعات را از collection دیگر خود (authors) می خواهیم و این مقدار را به آن پاس داده ایم. توجه کنید که تمام این مقادیر در کد بالا درون double quotation (علامت "") هستند.
  • localField یعنی ارجاعات یا همان reference های موجود به آن اطلاعات (اطلاعاتی که قرار است در هم ادغام شوند) را در کجا پیدا کنم؟ ما reference را همان id نویسنده ها قرار داده بودیم و aggregate را روی books صدا زده ایم (local یا «محلی» یعنی روی همین books که متد aggregate صدا زده شده است نه روی collection دیگر) بنابراین باید فیلدِ authors را به آن بدهیم. توجه کنید که اینجا authors همان فیلد موجود در books است که حاوی id نویسنده ها بود و منظورمان collection ای به نام authors نیست (در اول جلسه کد های books را قرار داده ام، می توانید نگاه کنید).
  • foreignField: کلمه foreign به معنی «خارجی» دقیقا خلاف local به معنی «محلی» است. به عبارت دیگر foreignField یا «فیلد خارجی» می گوید اطلاعات مورد نظر در کدام قسمت از collection دیگر (authors) قرار دارند. چون ما Aggregate را روی books صدا زده ایم، books می شود محلی و authors می شود خارجی. من می دانم که اطلاعات reference برای نویسنده همان id شان است بنابراین باید فیلد id_ را به آن پاس بدهیم (reference در کالکشن books درون فیلد authors بود و در کالکشن authors درون فیلدِ id است). برای راحت تر شدن موضوع اینطور فکر کنید: من می دانیم که درون books آیدی هایی را به عنوان reference دارم که مقدار اصلی شان در فیلد id_ درون کالکشن authors گرفته شده است.
  • as یک alias (به معنی «نام مستعار») است. به عبارت دیگر اطلاعات نویسنده ها را که از authors دریافت کردیم، تحت چه عنوانی وارد books کنیم؟ من اینجا نام دلخواه خودم را انتخاب کرده ام که Creators است (شما می توانید هر نام دیگری را انتخاب کنید).

نکته مهم: این کد برای دریافت داده ها است بنابراین زمانی که آن ها اجرا کنید واقعا مقادیر موجود در authors و book را در هم ادغام نمی کند، بلکه یک document جدید را بر اساس شرط ما ساخته و آن را به ما پاس می دهد. collection های ما و document های ما هیچ گونه تغییری نخواهند کرد (این متد فقط یک متد read یا خواندن اطلاعات است).

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

        "_id" : ObjectId("5e8882355159280df164b054"),
        "name" : "My favorite Book",
        "authors" : [
                ObjectId("5e8882d85159280df164b055"),
                ObjectId("5e8882d85159280df164b056")
        ],
        "creators" : [
                {
                        "_id" : ObjectId("5e8882d85159280df164b055"),
                        "name" : "Amir",
                        "age" : 24,
                        "address" : {
                                "street" : "Main"
                        }
                },
                {
                        "_id" : ObjectId("5e8882d85159280df164b056"),
                        "name" : "Nastaran",
                        "age" : 30,
                        "address" : {
                                "street" : "Far"
                        }
                }
        ]
}

همانطور که می بینید، در اطلاعات برگشتی فیلد جدیدی به نام creators (نام دلخواه من) به وجود آمده است که حاوی اطلاعات نویسنده ها از یک collection دیگر است! بنابراین این متد بسیار کاربردی است و به ما کمک می کند که به جای اجرای چندین کوئری، اطلاعات خودمان را یکجا دریافت کنیم.

سوال: حالا که این متد را داریم آیا باید همیشه از reference ها استفاده کنیم؟

پاسخ: خیر! طبق مواردی که در جلسات قبل ذکر کردیم اگر روابط بین داده ای شما با embedded document همخوانی دارند حتما از embedded document ها استفاده کنید چرا که فشار کمتری روی پایگاه داده می آورد. دستور aggregate و lookup باید در پس زمینه اطلاعات را ادغام کنند بنابراین نسبت به embedded documents نیاز به منابع بیشتری دارند (این تفاوت ها در حد میلی ثانیه است و نباید فکر کنید که استفاده از aggregate باعث ضربه زدن به وب سایت شما می شود).

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

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

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