# koa实现知乎关注与粉丝的数据结构
# 分析关注与分析的数据结构
我们是否要把关注和粉丝都设计成列表呢?
- 显然是不行的,如果一个大V粉丝有100万,那么这个用户下就要存100万条粉丝用户的信息,这样设计是不合理的。 所以我们把关注设置成一个Schema,粉丝可以通过user表来限制条件获取。
# models/user.js
- 首先我们要在user集合中添加关注字段, 以便于我们将来通过following字段来获取对应的用户
const mongoose = require('mongoose');
const { Schema, model } = mongoose;
const userSchema = new Schema({
__v: { type: Number, select: false },
name: { type: String, required: true },
password: { type: String, required: true, select: false },
// ......
following: {
// { type: Schema.Types.ObjectId, ref: 'User' } 这行代码表示引用User集合中的数据
// 规定就这么写
type: [{ type: Schema.Types.ObjectId, ref: 'User' }],
select: false,
},
}, { timestamps: true });
module.exports = model('User', userSchema);
# controller/user.js
- 获取粉丝和关注接口
class UsersCtl {
// ......
async listFollowing(ctx) {
// 找到对应id User的关注列表,并返回查找id的其他字段
const user = await User.findById(ctx.params.id).select('+following').populate('following');
if (!user) { ctx.throw(404, '用户不存在'); }
ctx.body = user.following;
}
async listFollowers(ctx) {
const users = await User.find({ following: ctx.params.id });
ctx.body = users;
}
async follow(ctx) {
// 获取自己的信息
const me = await User.findById(ctx.state.user._id).select('+following');
// 如果自己没有关注过
if (!me.following.map(id => id.toString()).includes(ctx.params.id)) {
me.following.push(ctx.params.id);
me.save();
}
ctx.status = 204;
}
async unfollow(ctx) {
// 获取自己的信息
const me = await User.findById(ctx.state.user._id).select('+following');
const index = me.following.map(id => id.toString()).indexOf(ctx.params.id);
// 如果自己没有关注过
if (index > -1) {
me.following.splice(index, 1);
me.save();
}
ctx.status = 204;
}
}
module.exports = new UsersCtl();
# routes/user.js
- 添加路由即可
router.get('/:id/following', listFollowing);
router.get('/:id/followers', listFollowers);
router.put('/following/:id', auth, checkUserExist, follow);
router.delete('/following/:id', auth, checkUserExist, unfollow);