کوئری زدن به آرایه‌ها و اسناد تو در تو

?How to Query Nested Arrays and Documents

19 اردیبهشت 1401
درسنامه درس 32 از سری دوره جامع آموزش MongoDB
MongoDB: کوئری زدن به آرایه ها و اسناد تو در تو (قسمت 34)

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

// بقیه اطلاعات //
        "genres" : [
                "Comedy",
                "Family"
        ],
        "status" : "Ended",
        "runtime" : 30,
        "premiered" : "2009-09-30",
        "officialSite" : "http://abc.go.com/shows/the-middle",
        "schedule" : {
                "time" : "20:00",
                "days" : [
                        "Tuesday"
                ]
        },
        "rating" : {
                "average" : 8.2
        },
        "weight" : 95,
        "network" : {
                "id" : 3,
                "name" : "ABC",
                "country" : {
                        "name" : "United States",
                        "code" : "US",
                        "timezone" : "America/New_York"
                }
        },
// بقیه اطلاعات //

ما در داده های بالا network را داریم که درون خودش country را به صورت یک embedded document دارد. همچنین خصوصیت genres را داریم که دو مقدار comedy و family را در خود دارد. یا مثلا rating (امتیاز یک فیلم rating نام دارد) را داریم که درون خودش average را دارد. برای این نوع از داده ها چطور باید کوئری بزنیم؟ مثلا چطور به average (به معنی «میانگین») دسترسی داشته باشیم؟

من با embedded document ها شروع می کنم. نکته اول این است که حتما باید از double quotation (علامت های "") استفاده کنید. سپس به شکل یک شیء عادی در جاوا اسکریپت از اپراتور نقطه به موارد درون هم دسترسی خواهیم داشت. مثلا برای دسترسی به average می توان به شکل زیر عمل کرد:

db.movies.find({"rating.average": {$gt: 7}}).pretty()

همانطور که می بینید rating.average باید درون double quotation باشد. اپراتور gt هم که یعنی «بزرگ تر از» بنابراین تمام سریال ها و فیلم هایی را می خواهیم که متوسط امتیاز آن ها (همان خصوصیت Average) از 7 بیشتر باشد. همچنین اگر 10 سطح مختلف و document تو در تو داشته باشیم، می توانیم به همین روش آن ها را کوئری بزنیم.

آرایه ها چطور؟ مثلا در قسمت genres معمولا چندین ژانر سینمایی داریم اما این ژانر ها اعضای یک آرایه هستند. چطور به آن ها دسترسی پیدا کنیم؟ برای انجام این کار باید به شکل زیر عمل کنیم:

db.movies.find({genres: "Drama"}).pretty()

بنابراین بسیار ساده است اما دو نکته مهم وجود دارد:

  • اولا این کوئری case-sensitive است یعنی به بزرگ بودن یا کوچک بودن حروف حساس است بنابراین drama با Drama فرق دارد.
  • دوما این کوئری برای یک آرایه نوشته شده است بنابراین Drama فقط باید درون genres وجود داشته باشد. اینطور نیست که Drama تنها مقدار genres باشد و ممکن است 10 عضو درون genres داشته باشیم که Drama فقط یکی از آن ها باشد.

البته اگر می خواهید به MongoDB بگویید که قرار است genres فقط یک عضو به نام Drama داشته باشد باید کوئری را به شکل زیر تغییر دهید:

db.movies.find({genres: ["Drama"]}).pretty()

بنابراین با قرار دادن علامت های [] مشخص کرده ام که genres باید دقیقا برابر یک آرایه با یک عضو به نام Drama باشد.

اپراتورهای باقی مانده از comparison

حالا که با مطالب پایه ای آشنا شدیم، باید با اپراتور های باقی مانده نیز آشنا شویم. یادتان باشد که این اپراتور ها هنوز هم از نظر فنی جزو دسته اپراتور های مقایسه ای هستند. اولین اپراتور ما in$ است. اپراتور in$ به ما اجازه می دهد که چند مقدار مشخص را در یک کوئری هدف بگیریم. به طور مثال تصور کنید که می خواهیم به MongoDB بگوییم فیلم ها و سریال هایی را انتخاب کن که مدت زمان آن ها (runtime) فقط برابر با 30 یا 42 دقیقه باشد. برای این کار باید به شکل زیر عمل کنیم:

db.movies.find({runtime: {$in: [30, 42]}}).pretty()

ما از اپراتور in$ مانند هر اپراتور دیگری استفاده می کنیم اما مقدار پاس داده شده به آن حتما باید یک آرایه باشد که مقادیر مورد نظر شما به عنوان اعضای آن قرار بگیرند. اپراتور دوم ما nin$ است که مخفف not in (درون چیزی نبودن) را نشان می دهد. مثلا به کد زیر توجه کنید:

db.movies.find({runtime: {$nin: [30, 42]}}).pretty()

این کد فیلم ها و سریال هایی را پیدا می کند که runtime آن ها برابر 30 یا 42 نباشد یا به زبان ساده تر هر چیزی به جز 30 و 42 باشد. با این حساب خلاصه ای از کل اپراتور های مقایسه ای (comparison operators) را در لیست زیر مشاهده می کنید:

  • اپراتور eq$: مخفف equal و به معنی «مساوی». دقیقا معادل مقادیر پاس داده شده است. مثلا runtime دقیقا برابر 42 دقیقه باشد، نه کمتر و نه بیشتر.
  • اپراتور gt$: مخفف greater than و به معنی «بیشتر از». معادل مقادیری است که بیشتر از مقدار پاس داده شده باشند (خود مقدار را شامل نمی شود). مثلا runtime بیشتر از 42 یعنی 43 و 44 و الی آخر.
  • اپراتور gte$: مخفف greater than or equal to و به معنی «بیشتر از یا برابر با». معادل مقادیری است که یا مساوی با مقدار پاس داده شده باشند و یا از آن بزرگتر باشند. مثلا runtime برابر یا بیشتر از 42 یعنی 42 و 43 و 44 و الی آخر.
  • اپراتور lt$: مخفف less than و به معنی «کمتر از». معادل مقادیری است که کمتر از مقدار پاس داده شده باشند. مثلا runtime کمتر از 42 یعنی 41 و 40 و الی آخر.
  • اپراتور lte$: مخفف less than or equal to و به معنی «کمتر از یا برابر با». معادل مقادیری است که کمتر یا مساوی با مقدار پاس داده شده باشند. مثلا runtime کمتر یا مساوی با 42 یعنی 42 و 41 و 40 و الی آخر.
  • اپراتور ne$: مخفف not equal و به معنی «مساوی نیست». معادل مقادیری است که مساوی با مقدار پاس داده شده نباشند. مثلا runtime ای که مساوی با 42 نباشد یعنی هر عدد دیگری (چه بالاتر و چه پایین تر) به غیر از 42 مقبول است (2 یا 100 یا 1000000 یا 3.4 یا 41 همگی مقبول هستند چرا که 42 نیستند).
  • اپراتور in$: مخفف چیزی نیست و خود in به معنی «درون» می باشد. معادل یکی از مقادیر پاس داده شده به آن خواهد بود. مثلا runtime برابر با 42 یا 30 یعنی چه «42 یا 30» و چه «42 و 30» باشد کل سند به ما برگردانده می شود و مقبول هستند.
  • اپراتور nin$: مخفف not in و به معنی «درون نیست». معادل هر مقداری به غیر از مقدار پاس داده شده است. مثلا runtime ای که درون خود 30 یا 42 نداشته باشد یعنی هر مقدار دیگری به غیر از این دو، مقبول است. تفاوت این اپراتور با ne$ در این است که در ne$ فقط یک مقدار انتخاب می شود اما در nin$ چندین مقدار را انتخاب می کنیم.

در قسمت بعد به سراغ اپراتور های منطقی (Logical Operators) می رویم.

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

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

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