Mysql 通过sequelize协会寻找朋友

Mysql 通过sequelize协会寻找朋友,mysql,node.js,sequelize.js,Mysql,Node.js,Sequelize.js,我对mysql的续集还是比较陌生的,试图更好地理解关联是如何工作的。我已经创建了一个简单的应用程序,用户可以将彼此添加为好友,如果我是正确的,这将是一个多对多关系 我有一个用户表和一个朋友表。users表是一个典型的users表,friend_binds表的创建方式如下: CREATE TABLE `friend_binds` ( `id` char(36) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL, `friend_id` cha

我对mysql的续集还是比较陌生的,试图更好地理解关联是如何工作的。我已经创建了一个简单的应用程序,用户可以将彼此添加为好友,如果我是正确的,这将是一个多对多关系

我有一个用户表和一个朋友表。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
我最初的工作方式是每次我添加一个朋友时,会有两个条目进入到朋友绑定(a到B和B到a)。这种方法对我很有效,我可以拉朋友,不管他们是A还是B

原始用户模型关联:

User.associate = models => {
    User.hasMany(models.friendBind, {
      foreignKey: {
        name: 'parentId',
        allowNull: false
      },
      onDelete: 'cascade',
      hooks: true
    })
  }
FriendBind.associate = models => {
    FriendBind.belongsTo(models.user, {
      foreignKey: {
        name: 'parentId',
        type: DataTypes.UUID,
        allowNull: false
      },
      onDelete: 'cascade'
    })
  }
原始模型关联:

User.associate = models => {
    User.hasMany(models.friendBind, {
      foreignKey: {
        name: 'parentId',
        allowNull: false
      },
      onDelete: 'cascade',
      hooks: true
    })
  }
FriendBind.associate = models => {
    FriendBind.belongsTo(models.user, {
      foreignKey: {
        name: 'parentId',
        type: DataTypes.UUID,
        allowNull: false
      },
      onDelete: 'cascade'
    })
  }
我想看看我是否能做到,这样我就只需要在friend_binds表中输入一个条目(即A到B)。我最终想添加一个状态列(sent、seen、rejected等),我觉得每次都要更新两行只是做错了

我现在遇到的问题是,当我使用user.getFriends()时,它只会获取用户是朋友A(父id)的朋友。如果用户是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_运行的新查询绑定创建表

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个朋友。

A
用户
可以有许多朋友,而该朋友也是
用户
可以有许多同样是
用户
的朋友

显然,
用户
用户
之间存在多对多关系

要保持这种关系,您需要定义一个透视表。我称之为
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)
  }
}

一个
用户
可以有很多朋友,而这个朋友,也就是
用户
可以有很多朋友,也就是
用户

显然,
用户
用户
之间存在多对多关系

要保持这种关系,您需要定义一个透视表。我称之为
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)
  }
}

这仍然只适用于一种方式,它将只查找用户id位于user_id中的关系。因此,friend_id中的用户搜索他们的朋友,它仍然返回0个朋友使用此模型,在my getFriends函数中,我可以同时使用.getFriends和.getUserFriends。这对我来说很有效,我肯定我遗漏了一些关于关联的信息,在这些关联中我可以找到friend\u bind记录,其中用户id是父id或friend\u id。或者其他方式,你必须在
friends
中包含
用户朋友
。这仍然只适用于一种方式,它将只查找用户id位于用户id中的关系。因此,在朋友id中的用户搜索他们的朋友时,它仍然返回0个朋友使用此模型,在my getFriends函数中,我可以同时使用.getFriends和.getUserFriends。这对我来说很有效,我肯定我遗漏了一些关于关联的信息,在这些关联中我可以找到friend\u bind记录,其中用户id是父id或friend\u id。另外,您必须将
用户朋友
包含在
朋友
中。