Skip to content

12.3 沸点管理接口

沸点是一个交友论坛,跟朋友圈差不多,用于分享简短的图文消息。从数据上看它是一个小型的文章集合。我们参考文章集合的设计,设定沸点集合的字段如下:

  • content:沸点内容,必填。
  • images:沸点图片,数组。
  • created_by:沸点创建者,必填。
  • created_at:沸点创建时间。
  • group:所属圈子标识。

一共五个字段,已经可以覆盖业务需求了,点赞和评论的数据放在单独的集合中。我们需要创建一组圈子数据,与文章分类一样,是一组静态数据。在 config/static.js 中添加 groups 变量并导出:

js
const groups = [
  {
    key: "daily",
    label: "打工日常",
  },

  {
    key: "techno",
    label: "技术圈",
  },
  {
    key: "blind_date",
    label: "相亲角",
  },
  {
    key: "slack_off",
    label: "上班摸鱼",
  },
  {
    key: "eating",
    label: "早中晚吃啥",
  },
  {
    key: "playing",
    label: "下班去哪玩",
  },
  {
    key: "bigtea",
    label: "好大一个瓜",
  },
];
module.exports = { groups };

接着我们创建模型,新建 model/shortmsgs.js 文件,并导入上面的 group 变量:

js
const { ObjectId } = mongoose.Types;
const { groups } = require("../config/static");

const shortmsgsSchema = new mongoose.Schema({
  content: { type: String, required: true },
  images: { type: [String], default: [] },
  created_by: { type: ObjectId, required: true },
  created_at: { type: Date, default: Date.now },
  group: {
    type: String,
    enum: groups.map((group) => group.key),
    required: true,
  },
});

const Model = mongoose.model("shortmsgs", shortmsgsSchema);

模型创建之后,就可以进入路由开发的环节了。

12.3.1 创建沸点接口

新建路由文件 router/shortmsgs.js,并添加一个创建沸点的路由如下:

js
// router/shortmsgs.js
var StmsgsModel = require('../model/shortmsgs')

router.post('/create', async (req, res, next) => {
  let body = req.body
  try {
    let result = await StmsgsModel.create(body)
    res.send(result)
  } catch (err) {
    ...
  }
})

在路由文件 config/router.js 中注册该路由:

js
const stmsgsRouter = require("../router/shortmsgs.js");
const router = (app) => {
  ...
  app.use("/stmsgs", stmsgsRouter);
};

经过这一套标准流程,现在创建沸点的接口就能用了。我们测试调用该接口,返回结果如下:

12.3.2 沸点列表接口

沸点列表需要关联查询点赞和评论数据,因此要用到聚合管道,具体方法和文章列表类似。创建路径为 “/list”,方法为 GET 的沸点列表路由,代码如下:

js
router.get('/lists', async (req, res, next) => {
  let { group, user_id, orderby } = req.query
  try {
    let orderby = orderby || 'new'
    if(!['new', 'hot'].includes(orderby)) {
      return res.status(400).send({ message: 'orderby 参数错误' })
    }
    let where = { }
    if (group) {
      where.group = group
    }
    let result = await StmsgsModel.aggregate([
      { $match: where },
      ...
    ])
    res.send(result)
  } catch (err) {
    ...
  }
})

上面代码中接收了 group 参数表示圈子标识,支持通过圈子筛选沸点。同时根据 orderby 参数决定数据排序规则,支持按时间、按热度两种排序方式。

参数处理后进入聚合管道,第一个管道是过滤沸点,其余的管道逻辑代码如下:

js
[
  {
    $lookup: {
      from: "comments",
      localField: "_id",
      foreignField: "source_id",
      as: "comments",
    },
  },
  {
    $lookup: {
      from: "praises",
      localField: "_id",
      foreignField: "target_id",
      as: "praises",
    },
  },
  {
    $addFields: {
      is_praise: {
        $in: [ObjectId(user_id), "$praises.created_by"],
      },
      praises: {
        $size: "$praises",
      },
      comments: {
        $size: "$comments",
      },
    },
  },
  {
    $sort: orderby == "new" ? { created_at: -1 } : { comments: 1, praises: 1 },
  },
];

管道逻辑主要是查询集合对应的评论和点赞数量,并使用新的管道阶段 $sort 对文档排序。排序规则是根据一个或多个字段进行升降排序,其中 1 代表升序、-1 代表降序。

测试该接口,可以看到返回结果如下:

12.3.3 沸点评论与点赞接口

沸点的评论与点赞接口不需要重新开发,因为文章的评论与点赞接口已经兼容了沸点,我们可以直接使用,只需要在传参时使用正确的标识参数。

当使用评论相关接口时,参数传入 source_type=2;使用点赞相关接口时,参数传入 target_type=2,这样就能标记沸点内容,与文章的数据区分开。