So I have a many-to-many relationship with Sequelize. This code gives me an array of all the categories associated with the Post. It works to get this data. However, if I would like to make that list of categories into just a single key value pair of how many categories instead of the categories. How could I do that?
return models.Post.findAndCountAll({
limit: limit,
offset: offset,
include: [{
model: models.Category,
as: 'categories',
required: false,
}],
})
For example this is the current output:
{
"id": 1,
"name": "foo",
"categories": [
{
"id": 1,
"name": "bar"
}
]
}
The desired output:
{
"id": 1,
"name": "foo",
"categories": 10
}
EDIT: As suggestions for fixing this I tried doing this:
return models.Post.findAndCountAll({
group: ['post.id'],
attributes: {
include: [[db.sequelize.fn("COUNT", db.sequelize.col("categories.id")), "categoriesCount"]]
},
limit: limit,
offset: offset,
include: [{
model: models.Category,
as: 'categories',
required: true,
attributes: []
}],
raw: true,
subQuery: false
})
But that just gives me the error:
{
"message": "invalid reference to FROM-clause entry for table \"post\""
}
This is basically what I want to get back, i wrote it in SQL and tried it:
SELECT
cp.category_id as category_id,
p.name as post_name,
COUNT(p.id) as num_categories
FROM
category c,
category_post cp
JOIN
post p ON p.id = cp.category_id
WHERE
p.id = cp.post_id AND
p.created_at >= '2022-01-26' and p.created_at <= '2022-05-02'
GROUP BY
cp.category_id,
post_name
ORDER BY
num_categories DESC
Generated SQL with Sequelize:
Executing (default): SELECT "post"."id", count("post"."id") AS "count" FROM "post" AS "post" INNER JOIN ( "category_post" AS "categories->categoryPost" INNER JOIN "category" AS "categories" ON "categories"."id" = "categories->categoryPost"."category_id") ON "post"."id" = "categories->categoryPost"."post_id" GROUP BY "post"."id";
Executing (default): SELECT "post"."id", "post"."name", COUNT("categories"."id") AS "categoryCount", "categories->categoryPost"."id" AS "categories.categoryPost.id", "categories->categoryPost"."category_id" AS "categories.categoryPost.category_id", "categories->categoryPost"."post_id" AS "categories.categoryPost.post_id" FROM "post" AS "post" INNER JOIN ( "category_post" AS "categories->categoryPost" INNER JOIN "category" AS "categories" ON "categories"."id" = "categories->categoryPost"."category_id") ON "post"."id" = "categories->categoryPost"."post_id" GROUP BY "post"."id" LIMIT 3 OFFSET 0;
My models look like the following:
Post(id, name, created_at, updated_at)
Category(id, name,)
PostCategory(id, post_id,category_id)
In my Post model:
static associate(models) {
this.belongsToMany(models.Category, {
through: models.CategoryPost,
as: 'posts',
foreignKey: 'category_id',
onDelete: 'CASCADE'
})
}
In my Category model:
static associate(models) {
this.belongsToMany(models.Post, {
through: models.CategoryPost,
as: 'categories',
foreignKey: 'post_id',
onDelete: 'CASCADE'
})
}
The generated SQL based on Emma's answer:
Executing (default): SELECT count("Post"."id") AS "count" FROM "Post" AS "Post" INNER JOIN ( "category_Post" AS "categories->categoryPost" INNER JOIN "category" AS "categories" ON "categories"."id" = "categories->categoryPost"."category_id") ON "Post"."id" = "categories->categoryPost"."Post_id";
Executing (default): SELECT "Post"."id", "Post"."name", (COUNT("categories"."id") OVER (PARTITION BY "Post"."id")::int) AS "categories" FROM "Post" AS "Post" INNER JOIN ( "category_Post" AS "categories->categoryPost" INNER JOIN "category" AS "categories" ON "categories"."id" = "categories->categoryPost"."category_id") ON "Post"."id" = "categories->categoryPost"."Post_id" LIMIT 3 OFFSET 0;