如何在 NodeJS Sequelize 中按查询计算组
Posted
技术标签:
【中文标题】如何在 NodeJS Sequelize 中按查询计算组【英文标题】:How to count a group by query in NodeJS Sequelize 【发布时间】:2015-07-04 07:58:21 【问题描述】:在 Rails 中,我可以执行一个简单的 ORM 查询来查询模型拥有的点赞数:
@records = Model
.select( 'model.*' )
.select( 'count(likes.*) as likes_count' )
.joins( 'LEFT JOIN likes ON model.id = likes.model_id' )
.group( 'model.id' )
这会生成查询:
SELECT models.*, count(likes.*) as likes_count
FROM "models" JOIN likes ON models.id = likes.model_id
GROUP BY models.id
在 Node Sequelize 中,任何类似的尝试都会失败:
return Model.findAll(
group: [ '"Model".id' ],
attributes: ['id', [Sequelize.fn('count', Sequelize.col('"Likes".id')), 'likes_count']],
include: [ attributes: [], model: Like ],
);
这会生成查询:
SELECT
Model.id,
count(Likes.id) AS likes_count,
Likes.id AS Likes.id # Bad!
FROM Models AS Model
LEFT OUTER JOIN Likes
AS Likes
ON Model.id = Likes.model_id
GROUP BY Model.id;
哪个会产生错误:
column "Likes.id" must appear in the GROUP BY clause or be used in an aggregate function
它错误地选择了likes.id,我不知道为什么,也不知道如何摆脱它。
【问题讨论】:
总是选择加入模型的 id 是技术性的后续,并且不能被禁用。尝试将 likes.id 添加到您的组子句中 这个问题被mod删除了,答案是不要使用Sequelize。它经常产生使查询崩溃的无效 SQL(你有一份工作)。 Knex 查询构建器是一个更好的工具,它提供了与 rails 相同的关于 sql 的轻抽象。 Sql 已经是一个很好的抽象,不要让 Sequelize 对你不利。 @andy-ray 哪个版本的续集...? 你可以使用findAndCountAll
方法。请验证***.com/a/52857907/1709558
【参考方案1】:
This sequelize github issue 看起来完全像你的情况:
User.findAll(
attributes: ['User.*', 'Post.*', [sequelize.fn('COUNT', 'Post.id'), 'PostCount']],
include: [Post]
);
【讨论】:
【参考方案2】:要解决这个问题,我们需要升级到最新版本的 sequelize 并包含 raw = true, 这是我在经过大量迭代和偏离路线谷歌搜索后所做的事情。
getUserProjectCount: function (req, res)
Project.findAll(
attributes: ['User.username', [sequelize.fn('COUNT', sequelize.col('Project.id')), 'ProjectCount']],
include: [
model: User,
attributes: [],
include: []
],
group: ['User.username'],
raw:true
).then(function (projects)
res.send(projects);
);
我的参考模型在哪里
//user
var User = sequelize.define("User",
username: Sequelize.STRING,
password: Sequelize.STRING
);
//project
var Project = sequelize.define("Project",
name: Sequelize.STRING,
UserId:
type:Sequelize.INTEGER,
references:
model: User,
key: "id"
);
Project.belongsTo(User);
User.hasMany(Project);
迁移 ORM 后,在我的 postgres 服务器中创建“用户”和“项目”表。 这是 ORM 的 SQL 查询
SELECT
"User"."username", COUNT("Project"."id") AS "ProjectCount"
FROM
"Projects" AS "Project"
LEFT OUTER JOIN "Users" AS "User" ON "Project"."UserId" = "User"."id"
GROUP BY
"User"."username";
【讨论】:
我认为这是一个很好的例子,说明为什么要不惜一切代价避免使用 Sequelize。这不仅仅是对 SQL 的泄漏抽象,他们发明了自己的无意义抽象来修复自己的软件,例如"raw": true
。 SQL 已经是一个很好的抽象,Sequelize 只是在它之上引入了新的 bug。
+1 用于提示“raw = true”。没有它,我的续集(版本 3.27.0)表现得很疯狂。简单示例:model.findAll attributes: ['name', sequelize.fn('sum', sequelize.col('value'))] group: ['name']
输出的结构按“名称”分组(没关系),但不是 sum(value),而是其他第三列,绝对不相关。
@AndyRay 你能推荐一个更好的节点 ORM 吗? (使用纯 db 驱动程序(例如 sqlite)需要一些样板文件)以上是关于如何在 NodeJS Sequelize 中按查询计算组的主要内容,如果未能解决你的问题,请参考以下文章