You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Node Express+Sequelize PostgreSQL实现双向用户拉黑功能

实现用户拉黑功能(类似Instagram/Facebook)

1. 新增拉黑关系表

首先在PostgreSQL中创建存储拉黑关系的blocked_users表,用来记录拉黑与被拉黑的关联:

CREATE TABLE blocked_users (
  blocker_id INTEGER REFERENCES user(user_id) ON DELETE CASCADE,
  blocked_id INTEGER REFERENCES user(user_id) ON DELETE CASCADE,
  PRIMARY KEY (blocker_id, blocked_id),
  CHECK (blocker_id != blocked_id) -- 禁止用户拉黑自己
);

这个表用blocker_id(拉黑者ID)和blocked_id(被拉黑者ID)做联合主键,避免重复存储同一组拉黑关系;外键设置ON DELETE CASCADE确保用户删除后,关联的拉黑记录会自动清除;CHECK约束直接防止用户拉黑自己。

2. 定义Sequelize模型

在Sequelize项目中创建BlockedUser模型,并与User模型建立自关联:

BlockedUser模型(blocked-user.model.js)

const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');

class BlockedUser extends Model {}

BlockedUser.init({
  blocker_id: {
    type: DataTypes.INTEGER,
    allowNull: false,
    references: {
      model: 'user',
      key: 'user_id'
    }
  },
  blocked_id: {
    type: DataTypes.INTEGER,
    allowNull: false,
    references: {
      model: 'user',
      key: 'user_id'
    }
  }
}, {
  sequelize,
  modelName: 'BlockedUser',
  tableName: 'blocked_users',
  timestamps: false, // 无需 createdAt/updatedAt 字段
  indexes: [
    {
      unique: true,
      fields: ['blocker_id', 'blocked_id']
    }
  ]
});

module.exports = BlockedUser;

关联User模型

在User模型中添加双向关联,方便后续查询操作:

const User = require('./user.model');
const BlockedUser = require('./blocked-user.model');

// 关联当前用户拉黑的人
User.hasMany(BlockedUser, { foreignKey: 'blocker_id', as: 'blockedUsers' });
// 关联拉黑当前用户的人
User.hasMany(BlockedUser, { foreignKey: 'blocked_id', as: 'blockedByUsers' });

3. 实现拉黑/取消拉黑API接口

假设你已经通过认证中间件(比如JWT)能获取当前用户ID,以下是核心接口实现:

拉黑用户接口

// POST /api/users/block
app.post('/api/users/block', async (req, res) => {
  const { blockedId } = req.body;
  const currentUserId = req.user.id; // 从认证中间件拿当前用户ID

  // 基础校验
  if (currentUserId === blockedId) {
    return res.status(400).json({ message: '不能拉黑自己' });
  }

  // 检查目标用户是否存在
  const targetUser = await User.findByPk(blockedId);
  if (!targetUser) {
    return res.status(404).json({ message: '目标用户不存在' });
  }

  // 检查是否已拉黑该用户
  const existingBlock = await BlockedUser.findOne({
    where: { blocker_id: currentUserId, blocked_id: blockedId }
  });
  if (existingBlock) {
    return res.status(400).json({ message: '已拉黑该用户' });
  }

  // 创建拉黑记录
  await BlockedUser.create({
    blocker_id: currentUserId,
    blocked_id: blockedId
  });

  res.status(200).json({ message: '拉黑成功' });
});

取消拉黑接口

// DELETE /api/users/unblock
app.delete('/api/users/unblock', async (req, res) => {
  const { blockedId } = req.body;
  const currentUserId = req.user.id;

  const deletedCount = await BlockedUser.destroy({
    where: { blocker_id: currentUserId, blocked_id: blockedId }
  });

  if (deletedCount === 0) {
    return res.status(400).json({ message: '未拉黑该用户,无需取消' });
  }

  res.status(200).json({ message: '取消拉黑成功' });
});

4. 修改用户查询API(排除拉黑关系)

修改原有的“查询所有用户”接口,排除三类用户:当前用户自己、当前用户拉黑的人、拉黑当前用户的人:

const { Op } = require('sequelize');

// GET /api/users
app.get('/api/users', async (req, res) => {
  const currentUserId = req.user.id;

  // 获取当前用户拉黑的所有用户ID
  const blockedIds = await BlockedUser.findAll({
    attributes: ['blocked_id'],
    where: { blocker_id: currentUserId }
  }).then(rows => rows.map(row => row.blocked_id));

  // 获取所有拉黑当前用户的用户ID
  const blockingIds = await BlockedUser.findAll({
    attributes: ['blocker_id'],
    where: { blocked_id: currentUserId }
  }).then(rows => rows.map(row => row.blocker_id));

  // 合并需要排除的ID列表(去重+排除自己)
  const excludedIds = [...new Set([...blockedIds, ...blockingIds, currentUserId])];

  // 查询符合条件的用户
  const users = await User.findAll({
    where: {
      user_id: {
        [Op.notIn]: excludedIds
      }
    },
    attributes: ['user_id', 'name', 'email', 'is_active'] // 返回指定字段
  });

  res.status(200).json(users);
});

5. 验证测试场景

  • 用户A(user_id=1)拉黑用户B(user_id=2)后:
    • A查询用户列表:仅能看到C(user_id=3)
    • B查询用户列表:仅能看到C(user_id=3)
    • C查询用户列表:能看到A和B
  • A取消拉黑B后:三方互相可见

内容的提问来源于stack exchange,提问作者sumanth.js

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 12:13:12