Search code examples
node.jsmongodbexpresspipelineaggregation

Getting null array as result in mongodb aggregate pipeline


Here is my code, I have two collections called cart and product, First I want to take the id of the product from the cart and then from the product collection get the product details

collection cart

{
    "_id" : ObjectId("62f8086e29c549f34ab89df7"),
    "user" : ObjectId("62f3f8600e93c17d1c25c2ed"),
    "product" : [
        ObjectId("62f391b9482a375c4f83de8e"),
        ObjectId("62f39121482a375c4f83de8d"),
        ObjectId("62f39200482a375c4f83de8f")
    ]
}

collection product

{
    "_id" : ObjectId("62f39121482a375c4f83de8d"),
    "name" : "iphone 15",
    "category" : "mobiles",
    "price" : "125",
    "description" : "fastest iphone"
}
{
    "_id" : ObjectId("62f391b9482a375c4f83de8e"),
    "name" : "OnePlus Nord",
    "category" : "mobile",
    "price" : "40000",
    "description" : "budget phone of OnePlus"
}
{
    "_id" : ObjectId("62f39200482a375c4f83de8f"),
    "name" : "Samsung M33",
    "category" : "mobile",
    "price" : "25000",
    "description" : "mid range mobile"
}

Here is the function for getting the details

getcartProducts:(userId)=>{
        return new Promise(async(resolve,reject)=>{
            let cartItem=await db.get().collection(collection.CART_COLLECTION).aggregate([
                {
                    "$match":{user:objectId(userId)}
                   
                },
                {
                    "$lookup":{
                        "from":collection.PRODUCT_COLLECTIONS,
                        "let":{"prodList":'$product'},
                    
                        pipeline:[

                            {
                                
                                "$match":{ "$expr":{ "$in":["_id","$$prodList"],
                                    },
                                },
                            },
                        ],
                        "as":"cartItems"
                    
                    }
                }
            ]
            ).toArray()
            resolve(cartItem) 
          
        })

    }

Finally the function is called

router.get('/cart',verifyLogin,async (req,res)=>{
    let products=await userHelpers.getcartProducts(req.session.user._id)
    console.log(products)
    res.render('user/cart')
  })

The output is: Showing null array in cartItems: []

 [
  {
    _id: new ObjectId("62f8086e29c549f34ab89df7"),
    user: new ObjectId("62f3f8600e93c17d1c25c2ed"),
    product: [
      new ObjectId("62f391b9482a375c4f83de8e"),
      new ObjectId("62f39121482a375c4f83de8d"),
      new ObjectId("62f39200482a375c4f83de8f"),
      new ObjectId("62f39121482a375c4f83de8d")
    ],
    cartItems: []
  }
]

Solution

  • Use $_id instead of _id in $in operator. Mongo Playground

    // This is the raw query
    db.carts.aggregate([
      {
        "$match": {
          "user": ObjectId("62f3f8600e93c17d1c25c2ed")
        }
      },
      {
        "$lookup": {
          "from": "products",
          "as": "cartItems",
          "let": {
            "prodList": "$product"
          },
          pipeline: [
            {
              "$match": {
                "$expr": {
                  "$in": [
                    "$_id",  // note the change here, use $ for matching field in lookup collection
                    "$$prodList" // use $$ for matching variable
                  ],
                  
                },
                
              },
              
            },
            
          ],
          
        }
      }
    ])
    

    Change the following line in your example code:

    "$match":{ "$expr":{ "$in":["_id","$$prodList"],
    

    To:

    "$match":{ "$expr":{ "$in":["$_id","$$prodList"],
    

    This aggregation pipeline cane be simplified to: Mongo Playground

    [
      {
        "$match": {
          "user": ObjectId("62f3f8600e93c17d1c25c2ed")
        }
      },
      {
        "$lookup": {
          "from": "products",
          "as": "cartItems",
          "localField": "product",
          "foreignField": "_id"
        }
      }
    ]