【问题标题】:Sequelize findOne returned instance. Row is in dataValues, but direct properties on instance are undefined续集 findOne 返回的实例。行在 dataValues 中,但实例上的直接属性未定义
【发布时间】:2019-08-18 06:05:38
【问题描述】:

上下文:我正在测试一个进出数据库的简单模型。不是真正的测试,它是一些集成测试的先驱。使用 SequelizefindOne

问题:返回的模型实例上的直接数据,即 email.ulid、email.address、email.isVerified 未定义。

我的问题:为什么它们没有定义?

Sequelize: 5.15.0
Typescript: 3.5.3
mysql  Ver 15.1 Distrib 10.4.6-MariaDB

记录到数据库

await testingDatabase.sync({
  force: true
}).then(async () => {
  await Email.create({
    ulid: the_ulid.bytes,
    address: "dave@world.com",
    isVerified: false
  })
})

取回记录:

await Email.findOne({
  where: { 
    address: "dave@world.com"
  }
  , rejectOnEmpty: true //to shut typescript up
}).then( emailData => {
   console.log("Email: ", email)
})

Console.log of email 实例:

    Email:  Email {                                                                                                                                                      
      dataValues: {                                                                                                                                                      
        ulid: <Buffer 01 6c a3 36 11 9c 1e 9b a6 ce 60 b7 33 3e e7 21>,                                                                                                  
        address: 'dave@world.com',                                                                                                                                    
        isVerified: false,                                                                                                                                               
        deletedAt: null,                                                                                                                                                 
        createdAt: 2019-08-18T05:32:05.000Z,                                                                                                                             
        updatedAt: 2019-08-18T05:32:05.000Z                                                                                                                              
      },                                                                                                                                                                 
      ...,
      isNewRecord: false,
      ulid: undefined,
      address: undefined,
      isVerified: undefined,
      createdAt: undefined,
      updatedAt: undefined,
      deletedAt: undefined
    }

^^^ 如上所示,实例上的所有直接属性都是空的。

以下工作,但副作用是 isVerified 返回为 0 而不是 false,随后无法与原始数据进行直接比较。此外,我失去了模型实例的其他功能,这些功能将在更复杂的模型上派上用场:

Email.findOne({
  where: { address: "dave@world.com" }
, raw: true 
, rejectOnEmpty: true
})

这些也有效,但结果是 Typescript 抱怨返回的对象没有我随后访问的属性(尽管它们确实存在并且测试有效):

.then( emailData => {
  console.log("All getters: ", emailData.get())
  // AND
  console.log("All getters(plain): ", emailData.get({plain: true}))
  // AND
  console.log("toJSON: ", emailData.toJSON())
})

下一个(由 Vivek 建议),只要数据可用,就可以工作,但 JSON.parse 无法正确处理 Buffer:

const dataOnly = JSON.parse(JSON.stringify(emailData))

其他人抱怨 (SE answer) console.log 以某种方式错误打印了实例,但我访问这些属性的所有其他方式仍然未定义。

【问题讨论】:

  • 我还尝试了 mapToModelinstance 设置,希望它能刺激模型填充。它没有。
  • 观看github.com/sequelize/sequelize/issues/10917,尽管这只是解决了目前发现的一些变通办法的副作用,而不是“为什么它们未定义”的实际问题。
  • 完全相同的问题11326,因为这个问题存在于sequelize github上。

标签: node.js sequelize.js


【解决方案1】:

我遇到了同样的问题,但上下文略有不同。

我的解决方案是在我的 tsconfig.json 中使用 ESNext 目标。使用ES2021 或任何其他目标解决了这个问题。

【讨论】:

  • 截至 2021 年 9 月,这应该是公认的解决方案。完美运行。
【解决方案2】:

解决方案:

问题出在Babel 插件上。

根据 Sequelize/Typescript documentation 设置 Sequelize 模型,在表示模型字段的每个模型上定义类属性。

babel 插件:

"@babel/proposal-class-properties"

在:

plugins: [
  "@babel/proposal-class-properties"
, ...
]

将这些类属性转换为模型Class对象上的defineProperty()调用,由助手_defineProperty()依次调用:

  _defineProperty(this, "yourFieldName", void 0);

这会使用值undefined 初始化对象的属性。

显然,当findOne 随后尝试更新模型时,它拒绝覆盖模型上的这些现有属性。

【讨论】:

  • 感谢您抽出宝贵时间在这里调查并回答您自己的问题以帮助其他人:)
  • 同意,感谢您为我指出解决此问题的正确方向。配置插件以排除我的模型文件夹为我解决了这个问题:stackoverflow.com/questions/61960885/…
  • 抱歉,我无法弄清楚 解决方案 是什么。解决办法是什么?
  • @pihentagy 已经有一段时间了,但我相信我删除了上面的插件。
【解决方案3】:

给你,你可以试试JSON.parseJSON.stringify

Email.findOne({
  where: { 
    address: "dave@world.com"
  }
}).then( emailData => {
   const dataOnly = JSON.parse(JSON.stringify(emailData));
   console.log(dataOnly); // <--- YOUR DATA
   console.log(emailData); // <--- YOUR INSTANCE
})

"Typescript 抱怨返回的对象没有 我然后访问的属性”

.then( emailData => {
  console.log("All getters: ", emailData.get())
  // AND
  console.log("All getters(plain): ", emailData.get({plain: true}))
  return emailData.get({plain: true}); // <-- I think you forgot to return this
});

我认为该错误是因为您可能没有返回结果。检查上面的代码。

【讨论】:

  • 这是一个有用的尝试,谢谢。但不幸的是,它属于越来越多的不完全正确的解决方案。 JSON.parse 不会优雅地处理 Buffer,而是命名类型并给出一个十进制数数组。
  • @PaulParker,你从哪里得到这个错误:“但是 Typescript 抱怨返回的对象没有我然后访问的属性”
  • 这是一个打字稿错误。我可以忽略它,程序仍然可以正常运行,它只会让我的编辑器变得混乱。我使用@babel/preset-typescript,它在编译时丢弃打字稿,而不是尝试处理打字稿错误。这允许生产继续进行,即使面对棘手的 Typescript 问题。
  • 检查可能解决您的错误的更新答案,emailData.get({plain: true}) 对您来说是完美的解决方案。 @保罗帕克
  • 我要退货了。出现 Typescript 错误是因为我尝试从数据中删除字段,而 Typescript 不知道这些字段的存在。 .get().toJSON() 都没有给 TS 任何类型信息。
猜你喜欢
  • 1970-01-01
  • 2018-09-05
  • 2021-09-04
  • 1970-01-01
  • 2018-07-19
  • 2018-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多