Home > Software engineering >  sequelize count associated table rows
sequelize count associated table rows

Time:02-17

Using sequelize and mySQL, I have two tables: User and Post.

Relation between two tables is M : N

db.User.belongsToMany(db.Post, { through: "Likes", as: "Liked" });
db.Post.belongsToMany(db.User, { through: "Likes", as: "Likers" });

What I want is getting post with whole likers id and count of whole likers.

I know how to get whole likers like this.

const post = await Post.findOne({
  where: { id: postId },
  attributes: ["id", "title", "imageUrl"],
  include: [{
    model: User,
    as: "Likers",
    attributes: ["id"],
    through: { attributes: [] },
  }]
})

// result
{
  "id": 36,
  "title": "test",
  "imageUrl": "하늘이_1644886996449.jpg",
  "Likers": [
    {
      "id": 13
    },
    {
      "id": 16
    }
  ]
}

And, I also know how to get count of whole likers.

const post = await Post.findOne({
  where: { id: postId },
  attributes: ["id", "title", "imageUrl"],
  include: [{
    model: User,
    as: "Likers",
    attributes: [[sequelize.fn("COUNT", "id"), "likersCount"]],
  }]
})

// result
{
  "id": 36,
  "title": "test",
  "imageUrl": "하늘이_1644886996449.jpg",
  "Likers": [
    {
      "likersCount": 2
    }
  ]
}

But, I don't know how to get both of them at once. Check the result when I use both of them.

{
  model: User,
  as: "Likers",
  attributes: ["id", [sequelize.fn("COUNT", "id"), "likersCount"]],
  through: { attributes: [] },
}

// result
"Likers": [
  {
    "id": 13,
    "likersCount": 2
  }
]

It only shows 1 liker(id: 13) It must show another liker(id: 16).

What is the problem?

CodePudding user response:

It shows only one because COUNT is an aggregating function and it groups records to count them. So the only way to get both - use a subquery to count records in a junction table while getting records on the other end of M:N relationship.

const post = await Post.findOne({
  where: { id: postId },
  attributes: ["id", "title", "imageUrl", 
  // you probably need to correct the table and fields names
  [Sequelize.literal('(SELECT COUNT(*) FROM Likes where Likes.postId=Post.id)'), 'LikeCount']],
  include: [{
    model: User,
    as: "Likers",
    attributes: ["id"],
    through: { attributes: [] },
  }]
})
  • Related