【问题标题】:Sequelize `findOne` working was not as expectedSequelize `findOne` 工作不如预期
【发布时间】:2021-02-27 16:44:22
【问题描述】:

我遇到了一个一周没能解决的问题......

当我将用户的电子邮件传递给数据库的查询时,sequelize 似乎一切正常并执行了这个查询,它从表中返回数据以及找到的结果,但执行findOne 函数的结果不是一个模型,为什么会发生这种情况,我该如何解决?

const email = 'email@example.com'
const user = await User.findOne({ where: { email }})

console.log(user.password) // undefined

这里是模型、服务和数据库连接

模型

import { DataTypes, Model } from "sequelize"
import { connection } from "./database"

class User extends Model {
  readonly id: number
  readonly email: string
  password: string
  username: string
  readonly createdAt: Date
  readonly updatedAt: Date
}

User.init(
  {
    id: {
      type: DataTypes.INTEGER,
      autoIncrement: true,
      primaryKey: true,
    },
    email: {
      type: DataTypes.STRING,
      unique: true,
    },
    password: {
      type: DataTypes.STRING,
    },
    username: {
      type: DataTypes.STRING,
    },
  },
  {
    sequelize: connection,
    modelName: "users",
    createdAt: "created_at",
    updatedAt: "updated_at",
  }
)

export default User

服务

export async function loginUser(email: string, password: string):  Promise<ServiceResponse<string>> {
  try {
    const user = await User.findOne({ where: { email } })
    if (!user) {
      throw Error("User not found")
    }

    if (!bcrypt.compareSync(password, user.password)) {
      throw Error("User not found or password did not match")
    }

    const { password: _, ...payload } = user.toJSON()
    const token = jwt.sign(payload, environment.jwt)

    return { success: true, content: token }
  } catch (error) {
    return { success: false, error: error.message }
  }
}

数据库连接

import { Sequelize } from "sequelize"
import { environment } from "../environment"

export const connection = new Sequelize(environment.database, {
  dialect: "postgres",
  logging: console.log,
  dialectOptions: {
    ssl: {
      rejectUnauthorized: false,
    },
  },
})

这是日志

Executing (default): SELECT "id", "email", "password", "username", "created_at", "updated_at" FROM "users" AS "users" WHERE "users"."email" = 'email@example.com';
users {
  dataValues: {
    id: 9,
    email: 'email@example.com',
    password: '$2b$10$s0HFL9eBbcp3GcGkB9cDZuSiCjOEgfQB5lZLxhxXraRfvRF6voDfW',
    username: null,
    created_at: 2020-11-16T13:09:30.631Z,
    updated_at: 2020-11-16T13:09:30.631Z
  },
  _previousDataValues: {
    id: 9,
    email: 'email@example.com',
    password: '$2b$10$s0HFL9eBbcp3GcGkB9cDZuSiCjOEgfQB5lZLxhxXraRfvRF6voDfW',
    username: null,
    created_at: 2020-11-16T13:09:30.631Z,
    updated_at: 2020-11-16T13:09:30.631Z
  },
  _changed: Set(0) {},
  _options: {
    isNewRecord: false,
    _schema: null,
    _schemaDelimiter: '',
    raw: true,
    attributes: [
      'id',
      'email',
      'password',
      'username',
      'created_at',
      'updated_at'
    ]
  },
  isNewRecord: false,
  id: undefined,
  email: undefined,
  password: undefined,
  username: undefined,
  createdAt: undefined,
  updatedAt: undefined
}

已用堆栈NextJS, Sequelize, PostgreSQL

我做错了什么?

【问题讨论】:

    标签: node.js typescript postgresql sequelize.js next.js


    【解决方案1】:

    您是否检查过您的用户对象是否也未定义?

    尝试使用user.dataValues.password 获取密码。 或者你可以像这样添加raw: true const user = await User.findOne({ raw:true, where: { email }}).Sequelize 将只返回数据而不是模型实例。所以你可以使用user.password

    【讨论】:

      【解决方案2】:

      模型实例使用dataValues 属性的概念进行操作,该属性存储实例表示的实际值。 正如您在dataValues 下的打印输出中所见,您拥有您的模型:

      Executing (default): SELECT "id", "email", "password", "username", "created_at", "updated_at" FROM "users" AS "users" WHERE "users"."email" = 'email@example.com';
      users {
        dataValues: {
          id: 9,
          email: 'email@example.com',
          password: '$2b$10$s0HFL9eBbcp3GcGkB9cDZuSiCjOEgfQB5lZLxhxXraRfvRF6voDfW',
          username: null,
          created_at: 2020-11-16T13:09:30.631Z,
          updated_at: 2020-11-16T13:09:30.631Z
        },
        _previousDataValues: {
            (...)
      

      要从此dataValues 字段中获取数据,您可以使用get 方法。 还 findOne 返回一个承诺。

      所以综合来看,在你的情况下,我认为这应该可行

      const email = 'email@example.com'
      User.findOne({ where: { email }}).then(data => {
          console.log(data.get('password')
      });
      

      看看Sequelize Model documentation

      【讨论】:

        【解决方案3】:

        谢谢,在处理接收到的数据之前,答案是Model.get({ plain: true })

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-11-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-12-16
          • 1970-01-01
          • 2018-03-12
          • 1970-01-01
          相关资源
          最近更新 更多