Node.js 使用Sequelize多次连接同一个表

Node.js 使用Sequelize多次连接同一个表,node.js,sequelize.js,Node.js,Sequelize.js,我有以下型号: const User = Sequelize.define('user', { login: Sequelize.DataTypes.STRING, password: Sequelize.DataTypes.STRING, is_manager: Sequelize.DataTypes.BOOLEAN, notes: Sequelize.DataTypes.STRING }); const Bike = Sequelize.define('bi

我有以下型号:

const User = Sequelize.define('user', {
    login: Sequelize.DataTypes.STRING,
    password: Sequelize.DataTypes.STRING,
    is_manager: Sequelize.DataTypes.BOOLEAN,
    notes: Sequelize.DataTypes.STRING
});

const Bike = Sequelize.define('bike', {
    model: Sequelize.DataTypes.STRING,
    photo: Sequelize.DataTypes.BLOB,
    color: Sequelize.DataTypes.STRING,
    weight: Sequelize.DataTypes.FLOAT,
    location: Sequelize.DataTypes.STRING,
    is_available: Sequelize.DataTypes.BOOLEAN
});

const Rate = Sequelize.define('rate', {
    rate: Sequelize.DataTypes.INTEGER
});
Rate.belongsTo(User);
User.hasMany(Rate);
Rate.belongsTo(Bike);
Bike.hasMany(Rate);
我想选择自行车的平均价格,加上每辆自行车当前用户的价格:

    Bike.findAll({
        attributes: {include: [[Sequelize.fn('AVG', Sequelize.col('rates.rate')), 'rate_avg']],
        },
        include: [{
            model: Rate,
            attributes: []
        }, {
            model: Rate,
            attributes: ['rate'],
            include: [{
                model: User,
                attributes: [],
                where: {
                    login: req.user.login
                }
            }]
        }],
        group: Object.keys(Bike.rawAttributes).map(key => 'bike.' + key) // group by all fields of Bike model
    })
它构造以下查询:选择[bike].[id],[bike].[model],[bike].[photo],[bike].[color],[bike].[weight],[bike].[bike].[location],[bike].[bike].[rates]作为[rates.id],[rates].[rate]作为[bike]上的[bike]左外连接[rates]作为[rates]。[bike].[id]=[rates].[rates].[bikeId]左外连接[rates]为[rates]内连接[users]为[rates->user]在[rates].[userId]=[rates->user].[id]=[rates->user].[bike].[id]=[rates].[bike].[bike].[model],[bike].[photo],[bike].[color],[bike].[weight],[bike].[bike].[location],[bike].[bike].[bike].[Ike].[U]是否可用]

并且失败:SequelizeDatabaseError:在FROM子句中多次指定了相关名称“rates”

如何正确编写查询?我需要Sequelize为第二次联接中使用的rates表指定另一个别名,并将其列添加到GROUP BY子句,但这是下一步。

解决方案:

注意:阅读评论


Sequelize不支持通过同一关联包含两次,请参见和。在模型级别,您可以定义自行车和费率之间的两种不同关联,但必须更改模型、添加新外键等,这是一个非常棘手的解决方案

顺便说一句,这并不能解决您的另一个问题,即您只按自行车分组,但随后希望选择用户的费率。要解决这个问题,您还必须更改分组以包含用户费率。请注意,如果用户每辆自行车的费率超过1,这也可能会造成一些低效,因为自行车的费率会针对每个用户的费率重复平均

一个合适的解决方案是使用窗口功能,首先平均每辆自行车的费率,然后过滤掉所有不属于登录用户的费率。可能看起来像这样:

挑选* 从…起 选择自行车。*, users.login作为用户登录, 按bike.id划分的AVG rates.rate作为rate_AVG 从自行车 rates.bikeId=bike.id上的内部联接速率 rates.userId=users.id上的内部加入用户 其中user\u login=:req\u user\u login
不幸的是,据我所知,sequelize目前不支持FROM子句中的子查询,也不支持以这种方式使用窗口函数,因此您必须退回到原始查询。

您可以通过添加与该模型的额外相同关联来对同一表进行多个内部联接,但使用不同的别名,如:“alias1”,as:‘别名2’,…-所有这些都存在于相同的模型+相同类型的关联中。 还将此解决方案发布在github问题上:

例如,对于具有多个接收者的聊天 根据需要为多个用户复制关联

Chat.hasManyReceiver{ //外键:。。。 作为‘聊天接收者’, }; Chat.hasManyReceiver{ //外键:。。。 as:‘查特接收人2’, }; 现在,您可以使用不同的别名多次包含关联的模型,这样它就不会被覆盖。 因此,您可以在查询中使用它们,如下所示:

查特·芬德尔{ 属性:[id], 包括:[{ 要求:正确, 型号:接收机, as:'chatReceiver',//别名1 属性:[], 其中:{userID:1},//条件1 }, { 要求:正确, 型号:接收机, as:'chatReceiver2',//别名2 属性:[], 其中:{userID:2},//根据需要设置条件2 }] };
Bike.findAll({
        attributes: {include: [[Sequelize.fn('AVG', Sequelize.col('rates.rate')), 'rate_avg']],
    },
    include: [{
        model: Rate,
        attributes: []
    }, {
        model: Rate,
        required : false , // 1. just to make sure not making inner join
        separate : true , // 2. will run query separately , so your issue will be solved of multiple times 
        attributes: ['rate'],
        include: [{
            model: User,
            attributes: [],
            where: {
                login: req.user.login
            }
        }]
        group : [] // 3. <------- This needs to be managed , so please check errors and add fields as per error
    }],
    group: Object.keys(Bike.rawAttributes).map(key => 'bike.' + key) // group by all fields of Bike model
})