# koa实现知乎关注与粉丝的数据结构

# 分析关注与分析的数据结构

我们是否要把关注和粉丝都设计成列表呢?

  • 显然是不行的,如果一个大V粉丝有100万,那么这个用户下就要存100万条粉丝用户的信息,这样设计是不合理的。 所以我们把关注设置成一个Schema,粉丝可以通过user表来限制条件获取。

# models/user.js

  1. 首先我们要在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

  1. 获取粉丝和关注接口
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

  1. 添加路由即可
router.get('/:id/following', listFollowing);
router.get('/:id/followers', listFollowers);
router.put('/following/:id', auth, checkUserExist, follow);
router.delete('/following/:id', auth, checkUserExist, unfollow);