如何基于Mongoose建模实现用户主页的三种好友状态按钮?
实现用户主页的好友状态按钮:建模与聚合查询方案
我来帮你搞定这个用户主页好友按钮的问题!核心思路是把用户间的好友关系单独建模,再通过聚合查询把状态和目标用户信息绑定,这样就能动态显示对应的按钮了。
一、好友关系建模方案
你现有的User Schema保持不变就好,我们单独创建一个Friendship Schema来管理好友请求的状态——因为用户间的好友关系是双向的,而且有明确的状态(发起、通过),单独建模比在User里存数组要灵活得多,后续维护状态变更也更方便。
const mongoose = require('mongoose'); const friendshipSchema = new mongoose.Schema({ // 请求发起者ID requester: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true }, // 请求接收者ID recipient: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true }, // 好友状态:pending=已请求,accepted=已成为好友,rejected=已拒绝(可选) status: { type: String, enum: ['pending', 'accepted', 'rejected'], default: 'pending', required: true } }, { timestamps: true }); // 添加复合唯一索引,避免同一个用户向另一个用户重复发起请求 friendshipSchema.index({ requester: 1, recipient: 1 }, { unique: true }); const Friendship = mongoose.model('Friendship', friendshipSchema);
二、聚合查询:动态获取好友状态
当用户访问目标用户主页时,我们需要在查询目标用户信息的同时,关联当前登录用户与目标用户的好友状态。用MongoDB的聚合查询可以一步完成这个需求:
// 假设当前登录用户ID为 currentUserId,要访问的目标用户ID为 targetUserId const targetUser = await User.aggregate([ // 第一步:匹配目标用户的基本信息 { $match: { _id: mongoose.Types.ObjectId(targetUserId) } }, // 第二步:关联Friendship集合,查找双方的好友关系 { $lookup: { from: 'friendships', let: { targetId: '$_id', currentId: mongoose.Types.ObjectId(currentUserId) }, pipeline: [ { $match: { $expr: { // 匹配两种情况:当前用户发起请求给目标用户,或者目标用户发起请求给当前用户 $or: [ { $and: [{ $eq: ['$requester', '$$currentId'] }, { $eq: ['$recipient', '$$targetId'] }] }, { $and: [{ $eq: ['$requester', '$$targetId'] }, { $eq: ['$recipient', '$$currentId'] }] } ] } } }, { $project: { status: 1, _id: 0 } } // 只保留状态字段 ], as: 'friendshipStatus' } }, // 第三步:把数组格式的状态转为单个值(因为双方最多只有一条好友关系记录) { $addFields: { friendStatus: { $cond: { if: { $gt: [{ $size: '$friendshipStatus' }, 0] }, then: { $arrayElemAt: ['$friendshipStatus.status', 0] }, else: null } } } }, // 第四步:移除临时的friendshipStatus数组字段 { $project: { friendshipStatus: 0 } } ]); // 最终targetUser[0]会包含目标用户的基本信息 + friendStatus字段: // - friendStatus为null:显示「添加好友」按钮 // - friendStatus为'pending':显示「已请求」按钮(如果是当前用户发起的请求) // - friendStatus为'accepted':显示「已成为好友」按钮
补充业务逻辑提示
- 点击「添加好友」时:创建一条
Friendship记录,requester为当前用户ID,recipient为目标用户ID,状态默认pending。 - 处理好友请求时:找到对应的
Friendship记录,把status改为accepted。 - 前端渲染按钮时:根据返回的
friendStatus值,直接切换对应的按钮文本和样式即可。
内容的提问来源于stack exchange,提问作者Ashish Choudhary
相关产品推荐
相关产品推荐

