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

如何使用Mongoose实现删除用户后双方列表互不可见功能

双向删除后用户列表互不可见实现方案

你现有Schema设计的deleteList(存储当前用户主动删除的用户ID)、beenDeletedList(存储主动删除了当前用户的用户ID)两个字段完全可以满足需求,只需要补全删除操作的双向写入逻辑、列表查询的过滤规则即可。

一、修复现有Schema的导出错误

你当前Schema代码存在变量不匹配问题,定义的Model常量名为User,最后导出时写的是不存在的UserInfo,需要先修正:

const mongoose = require("mongoose");

const userSchema = new mongoose.Schema(
  {
    userName: {
      type: String,
    },
    deleteList: [{ type: mongoose.Types.ObjectId, ref: "User" }],
    beenDeletedList: [{ type: mongoose.Types.ObjectId, ref: "User" }],
  }
);

const User = mongoose.model("User", userSchema);
// 修正导出变量
module.exports = User;

二、补全删除操作的双向写入逻辑

当用户A删除用户B时,必须同时更新两个用户的关联列表,否则会出现单向屏蔽的异常,建议用MongoDB事务保证两个操作的原子性:

// 用户删除接口逻辑
exports.deleteUser = async (req, res, next) => {
  const { currentUserId, targetUserId } = req.body;
  const session = await mongoose.startSession();
  session.startTransaction();
  try {
    // 给当前操作的用户追加删除记录,用$addToSet避免重复插入相同ID
    await User.findByIdAndUpdate(
      currentUserId,
      { $addToSet: { deleteList: targetUserId } },
      { session }
    );
    // 给被删除的用户追加被删记录
    await User.findByIdAndUpdate(
      targetUserId,
      { $addToSet: { beenDeletedList: currentUserId } },
      { session }
    );
    await session.commitTransaction();
    res.send({ code: 200, msg: "删除成功" });
  } catch (err) {
    await session.abortTransaction();
    next(err);
  } finally {
    session.endSession();
  }
}

三、补全可见用户列表的过滤逻辑

列表需要排除三类用户:

  • 当前用户主动删除的用户(存在deleteList中)
  • 主动删除了当前用户的用户(存在beenDeletedList中)
  • 当前登录用户自身
    直接在数据库查询层面用$nin过滤即可,不要查全量数据后在内存过滤,性能更高。补全后的getSortedUsers代码如下:
exports.getSortedUsers = async (req, res, next) => {
  const currentUserId = req.body._id;
  // 仅查询需要用到的两个屏蔽列表字段,减少不必要的字段查询
  const currentUser = await User.findById(currentUserId).select("deleteList beenDeletedList");
  if (!currentUser) {
    return res.status(401).send({ code: 401, msg: "当前登录用户不存在" });
  }
  // 合并所有需要屏蔽的用户ID
  const blockUserIds = [
    ...currentUser.deleteList,
    ...currentUser.beenDeletedList,
    currentUserId
  ];
  // 查询所有不在屏蔽列表中的用户,可根据业务需求追加sort排序规则
  const visibleUserList = await User.find({
    _id: { $nin: blockUserIds }
  }).select("userName _id"); // 仅返回列表需要展示的字段,降低传输开销

  res.send({ code: 200, data: visibleUserList });
}

实现注意事项

  • 所有数组追加ID的操作统一用$addToSet,不要用$push,避免重复存储同一个用户ID造成数据冗余
  • 删除操作必须加事务,防止服务异常中断导致只更新了单边数据,出现屏蔽逻辑不一致的问题
  • 如果后续需要做取消删除/恢复好友功能,对应操作也要同步更新两个用户的deleteList和beenDeletedList,把对应ID从数组中移除即可

内容的提问来源于stack exchange,提问作者Yellow Clock

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 07:42:18