Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在sequelize中对联接表中的其他列进行ORM?_Javascript_Sequelize.js - Fatal编程技术网

Javascript 如何在sequelize中对联接表中的其他列进行ORM?

Javascript 如何在sequelize中对联接表中的其他列进行ORM?,javascript,sequelize.js,Javascript,Sequelize.js,我正在使用节点v9.5,sequelize v4.33(postgres方言) 我有两种一流的车型:驾驶员(特定人群)和汽车(通用品牌+车型组合)。到目前为止,它们已经被一个多对多联接表连接起来。现在我想开始跟踪该联接表上的其他属性,但在声明这些关系以便它们实际工作时遇到了困难 const Driver = sqlz.define('Driver', { id: { primaryKey: true, type: DataTypes.UUID }, name: DataTypes

我正在使用节点v9.5,sequelize v4.33(postgres方言)

我有两种一流的车型:
驾驶员
(特定人群)和
汽车
(通用品牌+车型组合)。到目前为止,它们已经被一个多对多联接表连接起来。现在我想开始跟踪该联接表上的其他属性,但在声明这些关系以便它们实际工作时遇到了困难

const Driver = sqlz.define('Driver', {
    id: { primaryKey: true, type: DataTypes.UUID },
    name: DataTypes.string
})

const Car = sqlz.define('Car', {
    id: { primaryKey: true, type: DataTypes.UUID },
    make: DataTypes.string,
    model: DataTypes.string
})

// old associations; worked great when requirements were simpler
Driver.belongsToMany(Car, {
    through: 'DriverCar',
    as: 'carList',
    foreignKey: 'driverId'
})

Car.belongsToMany(Driver, {
    through: 'DriverCar',
    as: 'driverList',
    foreignKey: 'carId'
})
现在我想开始追踪更多关于汽车和司机之间关系的信息,比如特定汽车的颜色

步骤1:我更新迁移脚本,向联接表添加一个新列,如下所示:

queryInterface.createTable( 'DriverCar', {
    driverId: {
        type: sqlz.UUID,
        allowNull: false,
        primaryKey: true,
        references: {
            model: 'Driver',
            key: 'id'
        }
    },
    carId: {
        type: sqlz.UUID,
        allowNull: false,
        primaryKey: true,
        references: {
            model: 'Car',
            key: 'id'
        }
    },
    createdAt: {
        type: sqlz.DATE,
        allowNull: false
    },
    updatedAt: {
        type: sqlz.DATE,
        allowNull: false
    },

    // new column for join table
    color: {
      type: Sequelize.STRING
    }
})
步骤2:我为
DriverCar
定义了一个新的sqlz模型:

const DriverCar = sqlz.define('DriverCar', {
    color: DataTypes.string
})
// Driver -> Car
Driver.hasMany(DriverCar, {
    as: 'carList',
    foreignKey: 'driverId'
})

// Car -> Driver
Car.hasMany(DriverCar, {
    foreignKey: 'carId'
})
(我假设我只需要定义有趣的属性,
driverId
carId
仍将从将定义的关联中推断出来。)

步骤3:我需要更新
驾驶员
汽车
驾驶员卡
之间存在的关联

这就是我被困的地方。我已尝试更新现有关联,如下所示:

Driver.belongsToMany(Car, {
    through: DriverCar, // NOTE: no longer a string, but a reference to new DriverCar model
    as: 'carList',
    foreignKey: 'driverId'
})

Car.belongsToMany(Driver, {
    through: DriverCar, // NOTE: no longer a string, but a reference to new DriverCar model
    as: 'driverList',
    foreignKey: 'carId'
})
执行时不会出错,但在尝试
driver.getCarList()
时,新的
color
属性不会从联接表中获取。(Sqlz被配置为记录每个SQL语句,并且我已验证没有请求来自联接表的属性。)

因此,相反,我尝试更明确地解释这种关系,将
Driver
关联到
DriverCar
,然后将
Car
关联到
DriverCar

const DriverCar = sqlz.define('DriverCar', {
    color: DataTypes.string
})
// Driver -> Car
Driver.hasMany(DriverCar, {
    as: 'carList',
    foreignKey: 'driverId'
})

// Car -> Driver
Car.hasMany(DriverCar, {
    foreignKey: 'carId'
})
我还告诉sqlz,
DriverCar
将没有标准的行id:

DriverCar.removeAttribute('id')
此时,请求驱动程序的carList(
Driver.getCarList()
)似乎可以工作,因为我可以看到在SQL中获取连接表道具。但储蓄失败了:

driverModel.setCarList([ carModel1 ])

UPDATE DriverCar
SET "driverId"='a-uuid',"updatedAt"='2018-02-23 22:01:02.126 +00:00'
WHERE "undefined" in (NULL)
错误:

SequelizeDatabaseError: column "undefined" does not exist
我假设发生此错误是因为sqzl不了解正确的方法来标识联接表中的行,因为我无法建立必要的关联。坦率地说,我不相信我做得对;我是ORMs新手,但我希望我需要指定4个关联:

  • Driver
    ->
    DriverCar
  • DriverCar
    ->
    Car
  • 汽车
    ->
    驾驶员汽车
  • DriverCar
    ->
    Driver

  • 概括地说:我有两个一级实体,以多对多关系加入。我正在尝试向关系中添加数据,发现ORM需要以不同的方式定义这些关联,并且在阐明新关联时遇到困难。

    关于别名的说明 在回答问题之前,我想指出,您选择别名(
    carList
    driverList
    )可能会更好,因为尽管自动生成的sequelize方法
    .setCarList()
    .setDriverList()
    确实有意义,但方法
    .addCarList()
    .addDriverList())
    .removeCarList()
    .removeDriverList()
    都是无稽之谈,因为它们只将单个实例作为参数,而不是列表

    对于我的答案,我不会使用任何别名,让Sequelize默认为
    .setCars()
    .setDrivers()
    .addCar()
    .removeCar()
    ,等等,这对我来说更有意义


    工作代码示例 我已经制作了一个100%自包含的代码来测试这一点。只需复制粘贴并运行它(在运行
    npm安装sequelize sqlite3
    之后):

    上面的代码按预期记录(至少我预期):

    请注意,这里没有秘密。请注意,您要查找的额外属性,
    color
    ,嵌套在查询结果中,而不是与
    Car
    Driver
    的嵌套级别相同。这是Sequelize的正确行为

    确保您可以运行此代码并获得与我相同的结果。我的Node版本不同,但我怀疑这可能与任何事情有关。然后,将我的代码与您的代码进行比较,看看您是否能够找出导致问题的原因。如果您需要进一步帮助,请随时发表评论:)


    关于带额外字段的多对多关系的说明 由于我无意中发现了这方面的问题,而且这与你的情况有关,我想我应该在我的回答中添加一个部分,提醒你注意建立一个过度复杂的多对多关系的“陷阱”(这是我在挣扎了一段时间后学到的一课)

    与其重复我自己的话,我只想简单地引用我在中所说的话,并添加链接供进一步阅读:

    连接表,即存在于关系数据库中表示多对多关系的表,最初只有两个字段(每个表的外键定义多对多关系)。虽然确实可以在该表上定义额外的字段/属性,即关联本身的额外属性(如您在本期标题中所述),但在这里需要注意:如果它变得过于复杂,则表明您应该将连接表“升级”为一个完整的实体

    进一步阅读:

    • 我自己回答的问题涉及sequelize中多对多关系的过度复杂设置:
    • 以及它的兄弟问题:

    这是sequelize不太引人注目的地方之一。不过,你应该能够找到司机,包括汽车,它应该带来所有领域。在查询中执行(使用include)而不是使用magicmethod@yBrodsky:谢谢你的提示。我相信我知道你所说的“而不是使用神奇的方法”是什么意思,但是我必须做更多的研究来兑现你的建议。我应该补充一点,sequelize上的这个问题表明
    包含
    的方法不会