mysql - 寻找具有 Sequelize 关联的 friend

标签 mysql node.js sequelize.js

我对 mysql 的 Sequelize 还很陌生,试图更好地理解关联是如何工作的。我创建了一个简单的应用程序,用户可以在其中相互添加为 friend ,如果我是正确的,这将是多对多关系?

我有一个用户表和一个friend_binds表。 users 表是一个典型的 users 表,friend_binds 表的创建如下:

CREATE TABLE `friend_binds` (
  `id` char(36) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
  `friend_id` char(36) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  `parent_id` char(36) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `friendKey` (`parent_id`,`friend_id`),
  CONSTRAINT `friend_binds_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE

我最初让它工作的方式是每次我添加一个 friend 时,都会在friend_binds中创建两个条目(A到B和B到A)。这个方法对我来说效果很好,无论A还是B我都能拉到 friend 。

原始用户模型关联:

User.associate = models => {
    User.hasMany(models.friendBind, {
      foreignKey: {
        name: 'parentId',
        allowNull: false
      },
      onDelete: 'cascade',
      hooks: true
    })
  }

原始 FriendBinds 模型关联:

FriendBind.associate = models => {
    FriendBind.belongsTo(models.user, {
      foreignKey: {
        name: 'parentId',
        type: DataTypes.UUID,
        allowNull: false
      },
      onDelete: 'cascade'
    })
  }

我正在尝试看看我是否可以做到这一点,这样我就只需要在我的friend_binds表中添加一个条目(即仅A到B)。我最终想添加一个状态列(已发送、已查看、已拒绝等),并且我觉得每次都必须更新两行只是做错了。

我现在遇到的问题是,当我执行 user.getFriends() 时,它只会获取用户是 friend A (parent_id) 的 friend 。我认为如果用户是 A 或 B 就应该能够找到记录,这是错误的吗?我是否只需要 .findAll() 两次,一次搜索parentId,一次搜索friendId?

这是新用户关联

User.associate = models => {
    User.belongsToMany(models.user, {
      as: "friends",
      through: "friend_binds",
      foreignKey: "userId",
      otherKey: "friendId"
    })
  }

在这种情况下,我在某处读到,我什至不需要定义我的friend_binds表,因为sequelize为我创建了它,所以我就是这样做的

为friend_binds创建表运行的新查询

CREATE TABLE `friend_binds` (
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  `user_id` char(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
  `friend_id` char(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
  PRIMARY KEY (`user_id`,`friend_id`),
  KEY `friend_id` (`friend_id`),
  CONSTRAINT `friend_binds_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `friend_binds_ibfk_2` FOREIGN KEY (`friend_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE

寻找好友的相关代码

module.exports.getFriendsNew = async (req, res) => {
  try {
    const user = await db.user
      .findByPk(req.user.id)
      .catch(error => { throw new Error(error) })

    const friends = await user
      .getFriends()
      .then(results => {
        if (results.length === 0) { throw new Error("You have no friends") }
        return results
      })
      .catch(error => { throw new Error(error) })

    res.send(friends)

  } catch (error) {
    res.send(error.message)
  }
}res.send(error)
  }

通过这段代码,我可以找到好友 A 的记录,但是如果我搜索好友 B,它会返回 0 个好友。

最佳答案

一个用户可以有很多 friend ,而那个 friend (同时也是用户)可以有很多 friend ,同时也是用户

毫无疑问,用户用户之间是多对多的关系。

要保持这种关系,您需要定义一个数据透视表。我将其称为 UsersFriends

因此您所拥有的关联将如下所示。

User.belongsToMany(models.User, { 
  as: 'friends',
  foreignKey: 'user_id',
  through: UsersFriends
});
User.belongsToMany(models.User, { 
  as: 'userFriends',
  foreignKey: 'friend_id',
  through: UsersFriends
});

// UsersFriends 
module.exports = (sequelize, DataTypes) => {
  const TaskSparePart = sequelize.define('UsersFriends', {
    user_id: DataTypes.BIGINT,
    friend_id: DataTypes.BIGINT,
    created_at: DataTypes.DATE,
    updated_at: DataTypes.DATE,
  }, {
    tableName: 'users_friends',
  });
  return UsersFriends;
};

// To get friends
module.exports.getFriends = async (req, res) => {
  try {
     const user = await db.User.findOne({
        where: {
        id: req.user.id,
        },
        include: 'friends'
    })
    if (!user) throw new Error('User not found!');
    res.send(user.friends);
  } catch (error) {
    res.send(error.message)
  }
}

关于mysql - 寻找具有 Sequelize 关联的 friend ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61907371/

相关文章:

php - 匿名用户的 Drupal 权限

python - 通过Python转换数据类型然后将数据加载到Mysql中

mysql - 在 MySQL 中映射选定值

php - 列出数组 php 中的数字

javascript - 访问 Underscore 模板中的 JADE 变量

mysql - 我将如何使用 nodejs sequelize 执行此 SQL 查询?

sails.js - 迁移 Sequelize 迁移

node.js - 在 Supabase 中使用 Express 框架部署 Node Js 应用程序(Edge Functions)

mysql - Nodejs - 在没有迁移的情况下向表中添加列?

mysql - 如何测量sequelize中的查询执行时间?