【问题标题】:Create Association in Sequelize to do a Left Join在 Sequelize 中创建关联以进行左连接
【发布时间】:2015-05-12 07:23:56
【问题描述】:

我想使用与此 SQL 代码相同的 Sequelize 进行左连接。

SELECT * FROM events LEFT JOIN zones ON event_tz=zid WHERE event_creator_fk=116;

我有两张表:eventszones(带有时区列表)。

在查询特定用户创建的所有事件时,我还想获取时区名称和有关 TZ 的其他详细信息。

通过查看示例代码、其他 Stack Overflow 问题和文档,我尽我所能尝试了多种解决方案组合。该查询始终有效,但不执行任何联接。也就是说,它下面的代码总是返回事件列表,但没有来自zones 表的时区数据。生成的 SQL 是正确的,只是它没有 ...LEFT JOIN zones ON event_tz=zid... 部分。

下面的代码是错误的。详情请参阅答案。

db.Event.findAll(
    { where: { event_creator_fk: someUserID } },
    { include: [{ model: db.Zone } ]}
);

如果我理解正确,在 sequelize 中添加表之间的关联会导致自动创建一个额外的列。这不是我想做的。我不希望 Sequelize 以任何方式修改表或数据库。我想设置我的数据库,它是没有 Sequelize 的表。因此,我没有打电话给sequelize.sync()。我不知道是否可以按照我想要的方式设置关联。

模型定义

module.exports = function (sequelize, DataTypes) {

    var Event = sequelize.define('Event', {

            eid: {
                type: DataTypes.INTEGER,
                primaryKey: true
            },
            event_tz: {
                type: DataTypes.INTEGER,
                primaryKey: true,
                references: "Zone",
                referencesKey: "zid"
            },
        }, {
            classMethods: {
                associate: function (models) {
                    return models.Event.hasOne(models.Zone);
                }
            },
            freezeTableName: true,
            timestamps: false,
            tableName: 'events'
        }
    );
    return Event;
};


module.exports = function (sequelize, DataTypes) {
    return sequelize.define('Zone', {
        zid: {
            type: DataTypes.INTEGER,
            primaryKey: true
        }
    }, {
        classMethods: {
            associate: function (models) {
                return models.Zone.belongsTo(models.Event);
            }
        },
        freezeTableName: true,
        timestamps: false,
        tableName: 'zones'
    });
};

表定义

DROP TABLE IF EXISTS zones;
CREATE TABLE IF NOT EXISTS zones (
    zid integer NOT NULL,
    country_code character(2) NOT NULL,
    zone_name text NOT NULL,
    PRIMARY KEY (zid)
);

DROP TABLE IF EXISTS events;
CREATE TABLE IF NOT EXISTS events (
    eid                             BIGSERIAL NOT NULL,
    event_tz                        SERIAL NOT NULL,
    PRIMARY KEY (eid),
    FOREIGN KEY (event_tz) 
        REFERENCES zones(zid) MATCH FULL ON DELETE RESTRICT
);

【问题讨论】:

    标签: node.js postgresql sequelize.js


    【解决方案1】:

    您需要反转关联并告诉 sequelize 您的外键。 belongsTo 的意思是“将 fk 添加到这个模型中”:

    models.Event.belongsTo(models.Zone, { foreignKey: 'event_tz');
    
    models.Zone.hasOne(models.Event, { foreignKey: 'event_tz');
    // or hasMany if this is 1:m
    

    【讨论】:

    • 感谢您的回复。我用.hasOne.hasMany 尝试了你的解决方案,但它仍然无法正常工作。我没有收到任何错误,为事件表返回结果,但我仍然得到区域 ID。我是否需要上述模型定义中指定的此代码:references: "Zone", referencesKey: "zid".
    • 我不明白的地方:有必要打电话给sequelize.sync()。我不希望 sequelize 修改我的表格。
    • 您不需要调用 sequelize.sync - 只有当您不想通过 sequelize 创建表时才需要。
    • 如果您的模型仍然有 zoneId 列,则您一定没有正确指定外键
    【解决方案2】:

    部分问题是我错误地使用了findAll 方法。查询选项whereinclude 应该作为同一对象的一部分包含在内。 findAll 的第一个参数是选项参数。有关详细信息,请参阅here。正确的代码应如下所示。

    db.Event.findAll(
        {
             where: { event_creator_fk: someUserID },
             include: [{ model: db.Zone } ]
        },
    );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-16
      • 1970-01-01
      • 1970-01-01
      • 2015-04-26
      • 2017-07-21
      相关资源
      最近更新 更多