【问题标题】:Sequelize how to properly create a User Data with constraints?续集如何正确创建具有约束的用户数据?
【发布时间】:2020-05-18 19:55:44
【问题描述】:

这个问题并不寻求作为“最佳实践”的答案,而是与我下面的内容相比更合适的方式。

基本上我有一个User 模型/表,它与UserScore 模型/表有此关联。

User.belongsTo(models.UserScore, { 
  foreignKey: {
    name: "userScoreId",
    allowNull: false,
    defaultValue: 1
  },
  as: "score",
  targetKey: "id"
})

然后UserScore模型定义为:

'use strict';
module.exports = (sequelize, DataTypes) => {
  const UserScore = sequelize.define('UserScore', {
    id: { type: DataTypes.INTEGER, allowNull: false, autoIncrement: true, unique: true, primaryKey: true },
    score: DataTypes.INTEGER,
    coins: DataTypes.INTEGER
  }, {});
  UserScore.associate = function (models) {
    UserScore.hasMany(models.User, {
      foreignKey: "userScoreId",
      sourceKey: "id"
    })
  };
  return UserScore;
};

我遇到的问题是我觉得我在执行下面的 Sequelize 查询不正确。

首先我创建UserScore 假设我知道userId,使用Facebook 是可行的,因为我可以从Facebook 获得id。但不是使用电子邮件和密码注册!这是第一个问题

在创建UserScore 之后,我创建了一个User 数据。这感觉太不对劲了。虽然它适用于使用 Facebook 登录,因为就像我说的,我有用于创建 UserScoreuserId,但如果我没有它怎么办(例如,使用电子邮件和密码注册)?

编辑:这个问题与关于约束的错误有关,因为我尝试制作 User 数据而没有先制作 UserScore。我现在无法重现它,因为我已经使用 UUId (https://www.npmjs.com/package/uuid-int) 修复了它。


AuthController.js

module.exports = {
    // SIGN UP WITH EMAIL AND PASSWORD
    signup: async (req, res, next) => {
      const email = req.body.email
      const password = req.body.password

      if (!email || !password) {
        return res.status(403).send({
          message: "Error! Required parameters are: {email} and {password}."
        })
      }

      // Check if there is a user with the same email
      db.User.findOne({
        where: { email: email }
      })
        .then(data => {
          if (data) {
            return res.status(409).send({
              message: "Email is already in use."
            })
          }

          // Create a new user...
          const newUser = {
            fbId: null,
            email: email,
            firstName: null,
            lastName: null,
            photoUrl: null
          }

          const newUserScore = {
            score: 0,
            userId: id, //// <---------- NO IDEA!!!
            coins: 0
          }

          db.UserScore.create(newUserScore)
            .then(userScoreData => {

              db.User.create(newUser)
                .then(data => {
                  console.log("Created new user! ✅")
                  // Generate the token
                  const token = signToken(newUser)
                  // Respond with token
                  res.status(200).json({ token })
                })
                .catch(err => {
                  console.log("Error creating a new user!!!." + err)
                  return res.status(409).send({
                    message: "An error has occured while creating a new user"
                  })
                })

            })
            .catch(err => {
              console.log("Error creating user score.")
              done(err, null, err.message)
            })
        })
        .catch(err => {
          console.log(err)
          res.status(500).send({
            message: "An error has occured while retrieving data."
          })
        })
    }
}

用户关系

【问题讨论】:

  • 问题标题是关于约束的。你想创造什么约束?从问题中并不清楚。

标签: javascript node.js express sequelize.js


【解决方案1】:

我尝试在没有先创建 UserScore 的情况下创建 User 数据。

您在UserUserScore 之间定义的外键约束 绝不会允许您在 User 表中添加 UserScore 表中不存在的 UserScoreId,因为这将违反 SQL 外键约束。这确实是一个约束!

据我了解(如果我错了,请纠正我), 您正在模拟用户可能有一个或多个分数的事实, 如果是这样,userId 应该在 UserScore 表中。

这样,如果不存在相同邮箱的用户,可以先添加用户,再添加用户分数。

因此,您必须更改定义 sequelize 关联的方式 并将userId 设置为UserScore 表的外键。

这是定义关联的方法

//will add userId to UserScore table 
User.hasMany(UserScore, {
    foreignKey: { name: "userId", allowNull: false, defaultValue: 1 },
    as: "score",
    targetKey: "id"
})

//same here, will add userId to UserScore table 
UserScore.belongsTo(User, {
    foreignKey: "userId",
    sourceKey: "id"
})

【讨论】:

  • 嘿,谢谢!我想让UserScore 表更像一个参考表,我不知道有没有这样的东西,你知道将用户的分数和其他东西分开。不过,我实际上考虑过这种方法。问题是关于约束的,你纠正了它。同时,我保留了我看似错误的做法,并通过使用 uuid-int 唯一地生成 id 解决了同样的问题。
  • 这允许您将分数与用户的任何其他内容分开,因为 tableUserScore 仅包含用户 ID。或者您所说的“参考表”是什么意思?
  • 不要介意reference table 的事情。我是 SQL 和服务器端的新手。我想我只是想说的是我从User 表中分离了分数、硬币和其他用户帐户的东西,如果我不遵循你上面的答案,我不应该(我相信):D但它已经存在了,也许在我的下一个项目中,我会做得更好。再次感谢!
猜你喜欢
  • 1970-01-01
  • 2018-01-02
  • 1970-01-01
  • 2013-05-21
  • 1970-01-01
  • 2017-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多