Мангуст запрашивает данные справочной коллекции с помощью aggrigate / populate

#mongodb #express #mongodb-query

#mongodb #выразить #mongodb-запрос

Вопрос:

Я новичок в MongoDB и Express JS

У меня есть модель продукта, которая выглядит как

 const productSchema = mongoose.Schema({
   name: String,
   title: String,
   brand_id: { type: mongoose.Schema.Types.ObjectId, ref: 'brand' },
   varient:[{
       country_id: { type: mongoose.Schema.Types.ObjectId,ref: 'countries'},
       max_retail_price : Number,
       profit_margin : Number
   }],
  

и модель упорядочения

  const orderTransactionSchema = mongoose.Schema({
       shop_id: { type: mongoose.Schema.Types.ObjectId, ref: 'shop' },
       brand_id:{ type: mongoose.Schema.Types.ObjectId, ref: 'brand' },
       product_id: { type: mongoose.Schema.Types.ObjectId, ref: 'product' },
       product_varient_id:{ type: mongoose.Schema.Types.ObjectId, ref: 'product.varient._id' },
       transaction_id:{ type: mongoose.Schema.Types.ObjectId, ref: 'transaction' }
})
module.exports = mongoose.model('order', orderTransactionSchema );
  

В моей коллекции продуктов каждый продукт может иметь несколько вариантов.
Но при сборе заказов пользователь может заказать только один вариант продукта в разделе «продукт».

Я пытаюсь отобразить заказы с конкретными деталями продукта и деталями варианта, но проблема в том, что когда я пытаюсь отобразить его с помощью заполнения / агрегирования, я получаю все варианты в массиве ответов. на самом деле, мне нужны только сведения об одном продукте и варианте, как в коллекции заказов.

Это то, что я пробовал

 order.aggregate([{ $match :{} },
{
   $lookup: {
     from: "products",
     localField: "product_id",
     foreignField: "_id",
     as: "product_data"
   }
},
 ]).exec(function(err,result){
    console.log(result);
 });
  

и я получаю результат в виде

 { _id: 5c8a010b8feeb875abc1b066,
   shop_id: 5c7d194ca10ea45c0c03a0ee,
   brand_id: 5c41a8c34272c61a176b7639,
   product_varient_id: 5c41a9f3f8e1e71aa75b4f32,
   transaction_id: 5c6670d5b6c63d0762c6cc77,
   product_id: 5c41aac4d45a731af564c433,
   product_data:
    [ { _id: 5c41aac4d45a731af564c433,
        brand_id: 5c41a8c34272c61a176b7639,
        image: 'test.jpg',
        varient:        //getting all the varients here
         [ { _id: 5c4ee531bc20b27948b3aa98,
             sell_rate_local: 66,
             country_id: 5c01149d3c20440a6b2e4928 },
           { _id: 5c4ee53bbc20b27948b3aa99,
             sell_rate_local: 66,
             country_id: 5c00e1697dd7a23f08bdae68 } ],
        __v: 0 } ] } ]
  

В таблице заказов есть porduct_id и есть product_varient_id
Я хочу заполнить только продукт с помощью product_varient_id.

Я также пробовал что-то с Populate

 order.find().
             populate([

                  { path: 'shop_id', model: 'shop',select : 'name accounts' },    //it works
                 { path: 'transaction_id', model: 'transaction' }, //it wrks                     
                { path: 'product_varient_id', model: 'product', select:'product.varient.name'},
                 ]).then(result =>
                 {
                    // console.log(result);
                 }).catch(err =>{

                //     console.log(err);
                 });
  

Это образец документа о продукте и заказе

Образец документа заказа :

 {  
   "_id":"5c77a025d65a892f6acf1803",
   "shop_id":"5c7d194ca10ea45c0c03a0ee",
   "brand_id":"5c41a8b44272c61a176b7638",
   "product_varient_id":"5c41a9f3f8e1e71aa75b4f32",
   "buy_rate":10,
   "buy_rate_after_discount":20,
   "product_mrp":30,
   "sell_rate":40,
   "customer_mobile":123456789,
   "status":true,
   "transaction_id":"5c6670c9b6c63d0762c6cc76",
   "product_id":"5c41a95ff8e1e71aa75b4f30",
   "createdAt":"2019-02-28T08:47:33.097Z",
   "updatedAt":"2019-02-28T08:47:33.097Z",
   "__v":0
}
  

Образец документа продукта :

 {  
   "_id":"5c41aac4d45a731af564c433",
   "recharge_type":[  
      "5c00d9cf7dd7a23f08bdae5e"
   ],
   "name":"25 OC - Product 1",
   "title":"First installation recharge",
   "description":"0.1 credit for first time installation",
   "offer_message":"Hi.. You got 0.1 credits..!!",
   "brand_id":"5c41a8c34272c61a176b7639",
   "buy_rate":20,
   "profit_margin":80,
   "image":"test.jpg",
   "varient":[  
      {  
         "_id":"5c4ee531bc20b27948b3aa98",
         "display_name":"testlia",
         "profit_margin":66,
         "max_retail_price":66,
         "sell_rate":66,
         "sell_rate_local":66,
         "country_id":"5c01149d3c20440a6b2e4928"
      },
      {  
         "_id":"5c4ee53bbc20b27948b3aa99",
         "display_name":"testrinu",
         "profit_margin":66,
         "max_retail_price":66,
         "sell_rate":66,
         "sell_rate_local":66,
         "country_id":"5c00e1697dd7a23f08bdae68"
      }
   ],
   "createdAt":"2019-01-18T10:30:28.991Z",
   "updatedAt":"2019-01-28T11:19:23.662Z",
   "__v":0
}
  

Комментарии:

1. Не могли бы вы опубликовать образцы документов из всех коллекций

2. @Anthony Winzlet Я уже добавил пример вывода, который я получаю из запроса. Основная проблема связана с коллекцией ‘product’ . В коллекции продуктов у меня есть другой документ. Это означает, что у одного продукта может быть несколько вариантов. Но в суммированном заказе есть только один вариант продукта purslchse. Поэтому я не могу заполнить только определенный идентификатор варианта, соответствующий этому заказу продукта.

3. @Anthony Winzlet не могли бы вы ответить, пожалуйста…

4. Если бы вы могли показать несколько образцов документов и желаемый результат, тогда только я могу вам помочь.

5. @Anthony Winzlet Я обновлю вопрос

Ответ №1:

MongoDB 3.6 или выше имеют новый синтаксис поиска

   db.orders.aggregate([{
      $lookup: {
        from: "products",
        let: {
          "productId": "$product_id",
          "productVarientId": "$product_varient_id"
        },
        pipeline: [
          { $match: {
              $expr: { $eq: [ "$_id", "$$productId" ]}
            }
          },
          { $addFields: {
              varient: {
                $filter: {
                  input: "$varient",
                  as: "varient",
                  cond: { $eq: [ "$$productVarientId", "$$varient._id" ] }
                }
              }
            }
          }
        ],
        as: "product_data"
      }
    }])
  

Вы можете проверить образец данных здесь

Комментарии:

1. Мне нужно поместить условие внутри match , но мне нужно проверить условие match только в том случае, если массив condition не пуст

2. @Anthony Winzlet можешь ответить?

3. @Sibinfrancis не могли бы вы подробнее изложить свою точку зрения, показать, что я могу в этом помочь? как я вижу, если вы хотите соответствовать условию, вы можете использовать его на первом этапе агрегирования. Если вы хотите изменить выходные данные. пожалуйста, поделитесь образцами данных.