Home > Mobile >  How can I count all category under productId?
How can I count all category under productId?

Time:01-11

So I'm still new using MongoDB, so what I'm trying to do here is count all category under productId who have same category. So the expected output should be 7. I used populate first but got stuck on how can I use the $count. Instead I use aggregate and then use $lookup, but i only empty array of product

CartSchema.js

const CartSchema = new mongoose.Schema({
    productId: {type: mongoose.Schema.Types.ObjectId, ref: 'Product'}
})

export default mongoose.model('Cart', CartSchema)

ProductSchema.js

const ProductSchema = new mongoose.Schema({
    category: {type: String, required: true},

})

export default mongoose.model('Product', ProductSchema)

I used this code to show the information under productId.

router.get('/categories', async (req, res) => {
    
  try {
    const cart = await Cart.find()
    .populate([
      {path: 'productId', select: 'category' },
    ]).exec()
    res.status(200).json(cart);     

  } catch (error) { 
    res.status(500).json({error: error.message})
  }
})

The result of populate method.

[
    {
        "_id": "63b410fdde61a124ffd95a51",
        "productId": {
            "_id": "63b410d6de61a124ffd9585b",
            "category": "CASE"
        },
    },
    {
        "_id": "63b41a679950cb7c5293bf12",
        "productId": {
            "_id": "63b41637e3957a541eb59e81",
            "category": "CASE"
        },
    },
    {
        "_id": "63b433ef226742ae6b30b991",
        "productId": {
            "_id": "63b41637e3957a541eb59e81",
            "category": "CASE"
        },
    },
    {
        "_id": "63b670dc62b0f91ee4f8fbd9",
        "productId": {
            "_id": "63b410d6de61a124ffd9585b",
            "category": "CASE"
        },
    },
    {
        "_id": "63b6710b62b0f91ee4f8fc13",
        "productId": {
            "_id": "63b410d6de61a124ffd9585b",
            "category": "CASE"
        },

    },
    {
        "_id": "63b671bc62b0f91ee4f8fc49",
        "productId": {
            "_id": "63b410d6de61a124ffd9585b",
            "category": "CASE"
        },
    },
    {
        "_id": "63b6721c62b0f91ee4f8fcc5",
        "productId": {
            "_id": "63b410d6de61a124ffd9585b",
            "category": "CASE"
        },
    ]

So I used this method, but instead, I just get an empty array

router.get('/categories', async (req, res) => {



 try {
    const cart = await Cart.aggregate([
      {
        $lookup: {
          from: 'product',
          localField: 'productId',
          foreignField: '_id',
          as: 'product'
        }
      },
      {
        $unwind: "$product"
      },
      {
        $group: {
          _id: "$product.category",
          total: {
            $sum: 1
          }
        }
      },
      {
        $sort: {total: -1}
      },
      {
        $project: {
          _id: 0,
          category: "$_id",
          total: 1
        }
      },
    

    ])
    res.status(200).json(cart);     

  } catch (error) { 
    res.status(500).json({error: error.message})
  }
})

CodePudding user response:

In the aggregation, the collection to perform the $lookup on should be products (with an s) rather than product.

The name of the collection that Mongoose creates in your database is the same as the name of your model, except lowercase and pluralized, as documented in the documentation.

Mongoose automatically looks for the plural, lowercased version of your model name. Thus, for the example above, the model Tank is for the tanks collection in the database.

(emphasis theirs)

When using the aggregation framework, your aggregation pipeline is sent to the database as-is. Mongoose doesn't do any sort of coercion or casting on it. So when writing aggregation pipelines you should more or less forget you're using Mongoose. What's important is the name of the underlying collection in Mongo, which is generated from your model name based on the mentioned rule.

You can also override the collection name yourself if desired, for example:

export default mongoose.model('Product', ProductSchema, 'xyz');

This will override Mongoose's default naming behavior and will name the collection xyz.

  • Related