Sudharsan Venkatraj
Sudharsan Venkatraj

Reputation: 35

How to use `$unwind` to iterate exact value

I am new to mongoose and mongodb.

In my addtocart schema I have added $lookups and projection to populate products in add to cart.

In current response product_purchase_quantity it was in array in add to cart collection it is key and value. So, in $lookups I tried to add {$unwind: '$product_purchase_quantity'} but after adding add_to_cart_products object prints twice. I don't know where the mistake was?

Below i have mentioned expected result.

AddToCart Schema:

  lookups: [
      {
        from: 'shop_db_products',
        let: {
          productId: '$add_to_cart_products.product',
          purchaseQuantity: '$add_to_cart_products.product_quantity',
          productItemId: '$add_to_cart_products.product_item',
        },
        pipeline: [
          {
            $match: { $expr: { $in: ['$_id', '$$productId'] } },
          },
          {
            $lookup: {
              from: 'shop_db_products',
              localField: 'product_id',
              foreignField: '_id',
              as: 'products',
            },
          },
          {
            $project: {
              _id: true,
              product: {
                _id: '$_id',
                product_name: '$product_name',
              },
              product_purchase_quantity: '$$purchaseQuantity',
              product_item: {
                $reduce: {
                  input: {
                    $filter: {
                      input: '$product_items',
                      cond: {
                        $in: ['$$this._id', '$$productItemId'],
                      },
                    },
                  },
                  initialValue: {},
                  in: {
                    _id: '$$this._id',
                    product_size: { $concat: [{ $toString: '$$this.product_size.value' }, '$$this.product_size.unit'] },
                    product_price: '$$this.product_price',
                    product_type: '$$this.product_type'
                  },
                },
              },
            },
          },
        ],
        localField: '',
        as: 'add_to_cart_products',
        model: 'ProductModel',
      },
    ],

AddToCart Collection

[
{
    
      "add_to_cart_user": "5f0076b7bd530928fc0c0285",
      "add_to_cart_products": [
        {
          "product": "5f05a0270b4f3a5c41c70826",
          "product_item": "5f05a0270b4f3a5c41c70877",
          "product_quantity": 5
        },
         {
          "product": "5f05a0270b4f3a5c41c70827",
          "product_item": "5f05a0270b4f3a5c41c70666",
          "product_quantity": 3
        }
      ],
      "add_to_cart_product_total": 5,
      "add_to_cart_discount": 50,
      "add_to_tax": "5eae321d21924800122f978e",
      "add_to_cart_grand_total": 500
    }
]

Current Response:

{
    "_id": "5fa2a09b3c6316482098f6ff",
    "add_to_cart_status_is_active": true,
    "add_to_cart_discount": 50,
    "add_to_cart_tax": 8,
    "add_to_cart_products": [
        {
            "product": {
                "_id": "5f05a0270b4f3a5c41c70826",
                "product_name": "Avery Apricot Sour"
            },
            "product_purchase_quantity": [
                5,
                3
            ],
            "product_item": {
                "_id": "5f05a0270b4f3a5c41c70877",
                "product_size": "22oz",
                "product_price": 13.99
            }
        },
        {
            "product": {
                "_id": "5f05a0270b4f3a5c41c70827",
                "product_name": "Avery Dugana"
            },
            "product_purchase_quantity": [
                5,
                3
            ],
            "product_item": {
                "_id": "5f05a0270b4f3a5c41c70666",
                "product_size": "22oz",
                "product_price": 8.99
            }
        }
    ]
}

Expected response:

{
    "_id": "5fa2a09b3c6316482098f6ff",
    "add_to_cart_status_is_active": true,
    "add_to_cart_discount": 50,
    "add_to_cart_tax": 8,
    "add_to_cart_products": [
        {
            "product": {
                 "_id": "5f05a0270b4f3a5c41c70826",
                "product_name": "Avery Apricot Sour"
            },
            "product_purchase_quantity": 5,
            "product_item": {
                "_id": "5f05a0270b4f3a5c41c70877",
                "product_size": "22oz",
                "product_price": 13.99
            }
        },
        {
            "product": {
                 "_id": "5f05a0270b4f3a5c41c70827",
                "product_name": "Avery Dugana"
            },
            "product_purchase_quantity": 3,
            "product_item": {
                "_id": "5f05a0270b4f3a5c41c70666",
                "product_size": "22oz",
                "product_price": 8.99
            }
        }
    ]
}

Product (shop_db_products) collection:

[
    {
        "_id": "5f05a0270b4f3a5c41c70826",
        "product_no": "PRO04087",
        "product_store_no": "1001",
        "product_dept_no": "Irish Whiskey",
        "product_name": "2Gingers",
        "product_overview": "No Overview",
        "product_items": [
            {
                "_id": "5f05a0270b4f3a5c41c70877",
                "product_item_number": "857566003019",
                "product_price": 20.99,
                "product_cost": 20.99,
                "product_size": "750ml",
                "product_type": "Bottle",
                "product_value": 0,
                "product_quantity": 0,
                "product_images": [
                    "pro04087-857566003019-1.png"
                ],
                "product_item_is_active": true
            }
        ]
    },
...
]

Upvotes: 0

Views: 179

Answers (2)

Aleksey Druzhinin
Aleksey Druzhinin

Reputation: 96

Another way Without reducer, with $unwind

https://mongoplayground.net/p/3uWA5pVBv83

db.addToCart.aggregate([
  {
    "$unwind": "$add_to_cart_products"
  },
  {
    "$lookup": {
      "from": "shop_db_products",
      "let": {
        "productId": "$add_to_cart_products.product",
        "purchaseQuantity": "$add_to_cart_products.product_quantity",
        "productItemId": "$add_to_cart_products.product_item"
      },
      "pipeline": [
        {
          "$match": {
            "$expr": {
              "$eq": [
                "$_id",
                "$$productId"
              ]
            }
          }
        },
        {
          "$unwind": "$product_items"
        },
        {
          "$match": {
            "$expr": {
              "$eq": [
                "$product_items._id",
                "$$productItemId"
              ]
            }
          }
        },
        {
          "$project": {
            "_id": true,
            "product": {
              "_id": "$_id",
              "product_name": "$product_name"
            },
            "product_purchase_quantity": "$$purchaseQuantity",
            "product_item": "$product_items"
          }
        }
      ],
      "as": "productResolved"
    }
  },
  {
    "$unwind": "$productResolved"
  },
  {
    "$group": {
      "_id": "$_id",
      "add_to_cart_products": {
        "$push": "$productResolved"
      }
    }
  }
])

Upvotes: 0

Tiya Jose
Tiya Jose

Reputation: 1419

You have to $unwind add_to_cart_products before performing $lookup

db.addToCart.aggregate([
  {
    $unwind: "$add_to_cart_products"
  },
  {
    $lookup: {
      from: "shop_db_products",
      let: {
        productId: "$add_to_cart_products.product",
        purchaseQuantity: "$add_to_cart_products.product_quantity",
        productItemId: "$add_to_cart_products.product_item"
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $eq: [
                "$_id",
                "$$productId"
              ]
            }
          }
        },
        {
          $project: {
            _id: true,
            product: {
              _id: "$_id",
              product_name: "$product_name",
              
            },
            product_purchase_quantity: "$$purchaseQuantity",
            product_item: {
              $reduce: {
                input: {
                  $filter: {
                    input: "$product_items",
                    cond: {
                      $eq: [
                        "$$this._id",
                        "$$productItemId"
                      ],
                      
                    },
                    
                  },
                  
                },
                initialValue: {},
                in: {
                  _id: "$$this._id",
                  product_size: "$$this.product_size",
                  product_price: "$$this.product_price",
                  product_type: "$$this.product_type"
                }
              }
            }
          }
        }
      ],
      as: "add_to_cart_products"
    }
  },
  {
    $unwind: "$add_to_cart_products"
  },
  {
    $group: {
      _id: "$_id",
      "add_to_cart_products": {
        $push: "$add_to_cart_products"
      }
    }
  }
])

MongoDB Playground

Upvotes: 1

Related Questions