如何计算postgres数据库中sequelize中的关联
How to count associations in sequelize in postgres database
我使用 sequelize 框架在 Node.js 中开发了 APIs。我使用 Postgres 数据库。请在下面找到我的 table 结构如下。
category
post
category_post
user_like
id
id
category_id
user_id
category_name
title
post_id
post_id
detail
image_url
我需要开发一个 API 来根据提供的类别 ID 和 return 类别的 post 过滤类别,每个 post 应该包含其中的喜欢总数.
示例 JSON 响应如下:
{
"data":{
"id":1,
"category_name":"category 1",
"posts":[
{
"id":1,
"title":"post 1",
"total_likes":50,
"image_url":"image.png"
}
]
},
"success":true
}
请找到我的代码如下:
sequelize.transaction().then(result => {
return category.findOne({
where: { "id": request.params.id }, include: [{
model: post,
as: "posts",
attributes: ["id","title","image_url"],
through: {
attributes: []
}
}],
attributes: ["id", "category_name"],
});
}).then(posts => {
let r = { "data": posts, "success": true }
response.status(200).json(r)
}).catch(function (err) {
console.log(err)
});
请指导我如何获得 post 的总点赞数。这个功能对我不起作用
有两个结点 table 供考虑,即 category_post
和 user_like
table。这些可以使用 many to many associations 来处理。为简单起见,在下面的代码中,我将 user_like
table 视为父 table posts
的一个简单子 table,剩下一个结 table 考虑。
此外,打开 sequelize logging 对困难的查询有很大帮助。
下面是我将如何设置映射。
let Category = sequelize.define('categories', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
category_name: DataTypes.STRING,
detail: DataTypes.STRING
},
{
tableName: 'categories',
timestamps: false
})
let Post = sequelize.define('posts', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
title: DataTypes.STRING,
image_url: DataTypes.STRING
},
{
tableName: 'posts',
timestamps: false
})
let UserLike = sequelize.define('UserLike', {
post_id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
user_id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
}
},
{
tableName: 'user_likes',
timestamps: false
})
Category.belongsToMany(Post, {
through: 'category_posts',
timestamps: false,
foreignKey: 'category_id',
otherKey: 'post_id'
})
Post.belongsToMany(Category, {
through: 'category_posts',
timestamps: false,
foreignKey: 'post_id',
otherKey: 'category_id'
})
Post.hasMany(UserLike, {
foreignKey: 'post_id',
sourceKey: 'id'
})
UserLike.belongsTo(Post, {
foreignKey: 'post_id',
targetKey: 'id'
})
然后我会使用这样的子查询。请注意,为了使其成为 sequelize subquery.
,文字 select 语句周围的括号是必需的
let results = await Category.findAll({
attributes: {
exclude: [ 'detail' ]
},
where: { id: request.params.id },
include: {
model: Post,
attributes: {
include: [
[ sequelize.cast(sequelize.literal('(select count(*) from user_likes as ul where ul.post_id = posts.id)'), 'integer'), 'likes' ]
]
}
}
})
这会产生以下结果:
[
{
"id": 1,
"category_name": "category 1",
"posts": [
{
"id": 1,
"title": "Post 1",
"image_url": "http://example.com/image1.png",
"likes": 3,
"category_posts": {
"category_id": 1,
"post_id": 1
}
},
{
"id": 2,
"title": "Post 2",
"image_url": "http://example.com/image2.png",
"likes": 2,
"category_posts": {
"category_id": 1,
"post_id": 2
}
}
]
}
]
或者,如 HarshIT
所建议,您可以在以下查询中使用聚合和 group by 子句:
let results = await Category.findAll({
attributes: {
exclude: [ 'detail' ],
include: [[sequelize.cast(sequelize.fn('COUNT', Sequelize.col('posts->UserLikes.post_id')), 'integer'), 'total_likes']]
},
where: { id: request.params.id },
include: {
model: Post,
include: {
model: UserLike
}
},
group: [
'categories.id',
'posts.id',
'posts->category_posts.category_id',
'posts->category_posts.post_id',
'posts->UserLikes.post_id',
'posts->UserLikes.user_id'
]
})
这将产生以下形式的结果:
[
{
"id": 1,
"category_name": "category 1",
"total_likes": 1,
"posts": [
{
"id": 1,
"title": "Post 1",
"image_url": "http://example.com/image1.png",
"category_posts": {
"category_id": 1,
"post_id": 1
},
"UserLikes": [
{
"post_id": 1,
"user_id": 5
},
{
"post_id": 1,
"user_id": 6
},
{
"post_id": 1,
"user_id": 9
}
]
},
{
"id": 2,
"title": "Post 2",
"image_url": "http://example.com/image2.png",
"category_posts": {
"category_id": 1,
"post_id": 2
},
"UserLikes": [
{
"post_id": 2,
"user_id": 5
},
{
"post_id": 2,
"user_id": 8
}
]
}
]
}
]
我使用 sequelize 框架在 Node.js 中开发了 APIs。我使用 Postgres 数据库。请在下面找到我的 table 结构如下。
category | post | category_post | user_like |
---|---|---|---|
id | id | category_id | user_id |
category_name | title | post_id | post_id |
detail | image_url |
我需要开发一个 API 来根据提供的类别 ID 和 return 类别的 post 过滤类别,每个 post 应该包含其中的喜欢总数.
示例 JSON 响应如下:
{
"data":{
"id":1,
"category_name":"category 1",
"posts":[
{
"id":1,
"title":"post 1",
"total_likes":50,
"image_url":"image.png"
}
]
},
"success":true
}
请找到我的代码如下:
sequelize.transaction().then(result => {
return category.findOne({
where: { "id": request.params.id }, include: [{
model: post,
as: "posts",
attributes: ["id","title","image_url"],
through: {
attributes: []
}
}],
attributes: ["id", "category_name"],
});
}).then(posts => {
let r = { "data": posts, "success": true }
response.status(200).json(r)
}).catch(function (err) {
console.log(err)
});
请指导我如何获得 post 的总点赞数。这个功能对我不起作用
有两个结点 table 供考虑,即 category_post
和 user_like
table。这些可以使用 many to many associations 来处理。为简单起见,在下面的代码中,我将 user_like
table 视为父 table posts
的一个简单子 table,剩下一个结 table 考虑。
此外,打开 sequelize logging 对困难的查询有很大帮助。
下面是我将如何设置映射。
let Category = sequelize.define('categories', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
category_name: DataTypes.STRING,
detail: DataTypes.STRING
},
{
tableName: 'categories',
timestamps: false
})
let Post = sequelize.define('posts', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
title: DataTypes.STRING,
image_url: DataTypes.STRING
},
{
tableName: 'posts',
timestamps: false
})
let UserLike = sequelize.define('UserLike', {
post_id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
user_id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
}
},
{
tableName: 'user_likes',
timestamps: false
})
Category.belongsToMany(Post, {
through: 'category_posts',
timestamps: false,
foreignKey: 'category_id',
otherKey: 'post_id'
})
Post.belongsToMany(Category, {
through: 'category_posts',
timestamps: false,
foreignKey: 'post_id',
otherKey: 'category_id'
})
Post.hasMany(UserLike, {
foreignKey: 'post_id',
sourceKey: 'id'
})
UserLike.belongsTo(Post, {
foreignKey: 'post_id',
targetKey: 'id'
})
然后我会使用这样的子查询。请注意,为了使其成为 sequelize subquery.
,文字 select 语句周围的括号是必需的let results = await Category.findAll({
attributes: {
exclude: [ 'detail' ]
},
where: { id: request.params.id },
include: {
model: Post,
attributes: {
include: [
[ sequelize.cast(sequelize.literal('(select count(*) from user_likes as ul where ul.post_id = posts.id)'), 'integer'), 'likes' ]
]
}
}
})
这会产生以下结果:
[
{
"id": 1,
"category_name": "category 1",
"posts": [
{
"id": 1,
"title": "Post 1",
"image_url": "http://example.com/image1.png",
"likes": 3,
"category_posts": {
"category_id": 1,
"post_id": 1
}
},
{
"id": 2,
"title": "Post 2",
"image_url": "http://example.com/image2.png",
"likes": 2,
"category_posts": {
"category_id": 1,
"post_id": 2
}
}
]
}
]
或者,如 HarshIT
所建议,您可以在以下查询中使用聚合和 group by 子句:
let results = await Category.findAll({
attributes: {
exclude: [ 'detail' ],
include: [[sequelize.cast(sequelize.fn('COUNT', Sequelize.col('posts->UserLikes.post_id')), 'integer'), 'total_likes']]
},
where: { id: request.params.id },
include: {
model: Post,
include: {
model: UserLike
}
},
group: [
'categories.id',
'posts.id',
'posts->category_posts.category_id',
'posts->category_posts.post_id',
'posts->UserLikes.post_id',
'posts->UserLikes.user_id'
]
})
这将产生以下形式的结果:
[
{
"id": 1,
"category_name": "category 1",
"total_likes": 1,
"posts": [
{
"id": 1,
"title": "Post 1",
"image_url": "http://example.com/image1.png",
"category_posts": {
"category_id": 1,
"post_id": 1
},
"UserLikes": [
{
"post_id": 1,
"user_id": 5
},
{
"post_id": 1,
"user_id": 6
},
{
"post_id": 1,
"user_id": 9
}
]
},
{
"id": 2,
"title": "Post 2",
"image_url": "http://example.com/image2.png",
"category_posts": {
"category_id": 1,
"post_id": 2
},
"UserLikes": [
{
"post_id": 2,
"user_id": 5
},
{
"post_id": 2,
"user_id": 8
}
]
}
]
}
]