You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Sequelize报错Model.getAttributes is not a function的排查咨询

问题:Sequelize模型getAttributes()调用随机报错

背景

拥有对象数组docs和用于构建对象的Sequelize模型model,处理流程如下:

let mappedChunk = await Promise.all(
        docs.map(async (item) => {
            const pg_item: any = await model.build({
                _pg_key: uuidv4(),
                _source: JSON.stringify(item),
            }).dataValues

            await baseMapping(item, pg_item)

            if (extraMapping) {
                const status = await extraMapping(item, pg_item)
            }
            return pg_item
        }),
    )

await model.bulkCreate(mappedChunk, bulkCreateOptions)

baseMapping和extraMapping用于将数组对象属性映射到Sequelize模型对应属性,这部分逻辑正常,对象可成功转为pg_items。

问题场景

处理一对多/多对多关联时,检查模型是否存在指定外键的代码如下:

const Model = pg_item.constructor

if (!(foreignKeyName in Model.getAttributes())) {...}

程序随机报错:"Model.getAttributes is not a function",日志显示Model为原生Object构造函数:

pg_item <---------  [object Object]
Model <---------  function Object() { [native code] }
...
TypeError: Model.getAttributes is not a function
    at /home/ulkash/Desktop/Cloned/mgn-sequelize/build/seeders/scripts/utils/relationsBinding.js:26:49
    at Generator.next (<anonymous>)

排查方向与解决建议

1. 根源分析

model.build().dataValues返回的是纯JavaScript对象,而非Sequelize模型实例。虽然多数情况下constructor会指向Sequelize模型,但如果baseMapping或extraMapping中存在修改pg_item原型、重新赋值对象,或者使用Object.assign/解构等操作覆盖了原对象的原型链,就会导致pg_item.constructor变回原生Object。

2. 具体解决方法

方法一:保留Sequelize实例,不直接取dataValues

不要直接提取dataValues,而是先保留模型实例,操作完成后再取dataValues用于批量创建:

docs.map(async (item) => {
    // 保留模型实例,不直接取dataValues
    const pg_instance = await model.build({
        _pg_key: uuidv4(),
        _source: JSON.stringify(item),
    })
    // 直接操作实例的dataValues(或直接操作实例属性)
    await baseMapping(item, pg_instance.dataValues)
    if (extraMapping) {
        await extraMapping(item, pg_instance.dataValues)
    }
    // 后续检查模型时直接用pg_instance.constructor
    const Model = pg_instance.constructor
    if (!(foreignKeyName in Model.getAttributes())) {
        // 逻辑处理
    }
    // 最后返回dataValues用于bulkCreate
    return pg_instance.dataValues
})

方法二:手动绑定模型引用

如果必须直接使用dataValues对象,可以在创建时手动给pg_item添加模型引用属性,避免依赖原型链:

const pg_item: any = await model.build({
    _pg_key: uuidv4(),
    _source: JSON.stringify(item),
}).dataValues
// 手动挂载模型引用
pg_item._model = model

后续检查时直接使用这个引用:

if (!(foreignKeyName in pg_item._model.getAttributes())) {...}

方法三:排查映射函数中的对象修改

检查baseMapping和extraMapping函数,确认是否存在以下操作:

  • 使用Object.assign({}, pg_item)创建新对象并覆盖原pg_item
  • 对pg_item进行解构后重新赋值
  • 修改pg_item的__proto__属性
    这些操作会破坏原对象的原型链,导致constructor指向原生Object。

内容的提问来源于stack exchange,提问作者uli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 13:32:46