۶ میلیون تومن هدیه🎁 + کلی آفر جذاب در کمپین تابستون🔥 تابستون کوتاهه پس بزن بریم 👇
۰ ثانیه
۰ دقیقه
۰ ساعت
۱۱ زهرا نمازی
تفاوت lookup ، populate
کیوان علی محمدی حل شده توسط کیوان علی محمدی

میشه لطفا درباره تفاوت lookup ، populate بگید و کلا زمانی که قراره رو lookup شرط بخوره و query‌ها پیچیده بشن هم آموزش بدید من الان پیچیده‌ترین query‌ها رو تو اس کیو ال راحت میزنم ولی همونو بخوام مونگو کنم واقعا گاهی نمیتونم مثلا query که جوین باشه شرط داشته باشه group & having  اس کیو ال هم داشته باشه یه همچین مثالی بزنید ممنون میشم 

سلام خدمت شما. lookup یک بخش از بحث aggregation‌ها در خود mongodb هست در حالی که populate یک متد بر روی mongoose و عملا populate در پشت صحنه از چندین کوئری مجزا برای تطبیق reference‌های تعریف شده در Model استفاده میکنه. اگر می‌خواید کوئری‌های پیچیده داشته باشید باید از aggregate framework خود mongo استفاده کنید که به صورت pipeline عمل می‌کنه و این یعنی در ابتدا مثلا 10000 رکورد رو انتخاب می‌کنه و بعدش group رو اجرا می‌کنه و در نهایت هم مثلا project میکنه. شما بر اساس نوع داده هایی که میخواین می‌تونید pipeline‌های کمتر یا بیشتری داشته باشید. از این لینک می‌تونید راهنمای aggregate framework رو ببینید.

کیوان علی محمدی ۱۱ دی ۱۳۹۹، ۰۷:۴۷

من با aggregate کار کردم مشکلم دقیقا تو همون pipeline هست زمانی که قراره دوتا collection با هم جوین بشن و شرط بخوره تو pipeline و دیگه به جا lookup باید let بزاریم ست کردن اینا واقعا واسم سخت بود و داکیومنت قبلا دیدم متوجه نشدم واسه همین گفتم تو یه مثال اگه توضیح بدید ممنون میشم 

زهرا نمازی ۱۱ دی ۱۳۹۹، ۰۸:۰۲

این مثال رو نگاه کنید و بگید کجاش براتون مشکله :

 

db.orders.insert([
  { "_id" : 1, "item" : "almonds", "price" : 12, "ordered" : 2 },
  { "_id" : 2, "item" : "pecans", "price" : 20, "ordered" : 1 },
  { "_id" : 3, "item" : "cookies", "price" : 10, "ordered" : 60 }
])
db.warehouses.insert([
  { "_id" : 1, "stock_item" : "almonds", warehouse: "A", "instock" : 120 },
  { "_id" : 2, "stock_item" : "pecans", warehouse: "A", "instock" : 80 },
  { "_id" : 3, "stock_item" : "almonds", warehouse: "B", "instock" : 60 },
  { "_id" : 4, "stock_item" : "cookies", warehouse: "B", "instock" : 40 },
  { "_id" : 5, "stock_item" : "cookies", warehouse: "A", "instock" : 80 }
])
db.orders.aggregate([
   {
      $lookup:
         {
           from: "warehouses",
           let: { order_item: "$item", order_qty: "$ordered" },
           pipeline: [
              { $match:
                 { $expr:
                    { $and:
                       [
                         { $eq: [ "$stock_item",  "$$order_item" ] },
                         { $gte: [ "$instock", "$$order_qty" ] }
                       ]
                    }
                 }
              },
              { $project: { stock_item: 0, _id: 0 } }
           ],
           as: "stockdata"
         }
    }
])

 

 

 

 

 

 

کیوان علی محمدی ۱۱ دی ۱۳۹۹، ۰۸:۱۱

اونجاهایی که یک $ گذاشته یا 2تا اول درک نمیکنم یعنی چی دوم کلا let که میخوایم بزاریم.

اگه بخوام چیزی که تو پروژه شرکت خودم درگیرش بودم و چون نتونستم کلا query ساده زدم و بعد توی جی اس هندلش کردم این بود که پروژه ما پکیج دلیوری هست یه کالکشن order , driver  داریم و قرار بود من بیام هزینه دریافتی  هر راننده به صورت هفتگی درارم که خوب من گروپ کردم رو هفته ولی مشکل اونجا بود واسم که این سه نوع تاریخ میخورد cancel, delivered, return یه ابجکت تایم داره که سه تا از فیلداش اینا هستن و من شرط date  نمیتونسم رو گروپم اعمال کنم هیچ جوری من نتونسم این تو مونگو اکی کنم

زهرا نمازی ۱۱ دی ۱۳۹۹، ۰۸:۲۲

خب بذارید من توضیح بدم.

در خط زیر :

let: { order_item: "$item", order_qty: "$ordered" }

ما با استفاده از let برای lookup میایم و متغییر تعریف می‌کنیم، در واقع این متغییرها فقط برای استفاده توی pipeline که در داخل lookup نوشته میشه استفاده میشه. برای دسترسی به فیلد‌های orders از علامت $ استفاده شده مثلا $item و این یعنی فیلد آیتم بیاد و داخل order_item قرار بگیره و برای متغییر بعدی هم همین طور.

 

حالا بیایم و pipeline رو بررسی کنیم:

[
	 { $eq: [ "$stock_item",  "$$order_item" ] },
	 { $gte: [ "$instock", "$$order_qty" ] }
]

در این فیلد‌ها که با $ مشخص شدن متعلق به یک کالکشن دیگه هستن به اسم warehouse و برای این که از متغییر‌های بخش let استفاده کنیم اونها رو با $$ مشخص می‌کنیم که در این جا بر اساس expr‌های که در pipeline داریم ازشون استفاده شده.

 

برای مساله خودتون به نظرم از driver شروع کنید و با orders یک aggregate ایجاد کنید و در بخش lookup در بخش متغییر‌ها تاریخ یک هفته پیش  رو تعریف کنید، حالا در بخش pipeline می‌تونید توی بخش match و expr‌ها از gte بر روی متغییر تعریف شده استفاده کنید و در نهایت هم با  $sum مقادیرشون رو جمع کنید. اینطوری میزان درآمد روزانه و ماهانه و هفتگی و سالیانه یک راننده رو می‌تونید مشخص کنید.

بهترین پاسخ
کیوان علی محمدی ۱۱ دی ۱۳۹۹، ۰۹:۰۰

یه همچین resulti  با اون چیزی که شما گفتید میشه ؟

 

زهرا نمازی ۱۱ دی ۱۳۹۹، ۰۹:۴۰

همچین خروجی بستگی به فیلد هایی داره که توی project انتخاب می‌کنید، طیص چیزی که گفتم فیلد‌های راننده و اون  داده‌های داخل lookup که با as مشخص میشن در خروجی نوشته میشه. 

کیوان علی محمدی ۱۱ دی ۱۳۹۹، ۰۹:۴۶

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

   {
        $project: {
          numWeek: { $week: '$time.create' },
          year: { $year: '$time.create' },
          cost: 1,
        }
      },
      {
        $group: {
          _id: { year: '$year', numWeek: '$numWeek' },
          costValue: {
            $sum: '$cost.total'
          },
          countOrder: { $sum: 1 }
        }
      }
زهرا نمازی ۱۱ دی ۱۳۹۹، ۰۹:۵۱

شما توی order سه تا فیلد تایم دارید، یعنی باید از هر سه تا استفاده کنید؟ 

کیوان علی محمدی ۱۱ دی ۱۳۹۹، ۱۰:۲۱

تایم یه ابجکت هست که 4تا فیلد داره create, pickup,deliver,return , خود کنسل هم یه فیلد دیگه دیتابیس هست حالا ما فقط orderهایی که status اونا یکی از این حالت‌ها deliver,return , cancel باشه باید بیاریم , این order‌ها طبیعی یکیشون time.deliver  داره یکی time.return و من نمیدونسم گروپ رو چی بزنم که بتونه هفته‌ها رو گروپ کنه 

زهرا نمازی ۱۱ دی ۱۳۹۹، ۱۰:۲۸

به نظرم در طراحی دیتابیس اگر فیلد‌ها جدا می‌شد بهتر بود، به هر حال درمرحله اول با match سفارش هایی که در اون چند وضعیت هستند رو فیلتر کنید و بعدش با group به اون مقادیر برسید، چون گروه بندی بر اساس هفته است حتما باید بازه شروع و پایان رو براش در نظر بگیرید مثلا از 5 هفته پیش. 

کیوان علی محمدی ۱۱ دی ۱۳۹۹، ۱۰:۵۱