查询以获取最新的三个用户,按日期排序 - Mongoose Node.js

Query to get latest three users, sort by date - Mongoose Node.js

这是来自Mongodb的数据 (Task.json)

    {
        "username": "john",
        "taskId": "001",
        "date": "2020-02-18T20:14:19.000Z",
    },
    {
        "username": "david",
        "taskId": "001",
        "date": "2020-02-18T21:48:19.000Z",
    },
    {
        "username": "john",
        "taskId": "002",
        "date": "2020-02-15T20:20:32.000Z",
    }
    ... many more

我想要达到的目标

这是我创建的一个示例,说明我希望如何响应:

{
  "tasks": [
    {
      "taskid": "001",
      "users": [
        {
          "username": "david",
          "date": "2020-02-18T21:48:19.000Z"
        },
        {
          "username": "john",
          "date": "2020-02-18T20:14:19.000Z"
        }
      ]
    },
    {
      "taskid": "002",
      "users": [
        {
          "username": "john",
          "date": "2020-02-15T20:20:32.000Z"
        }
      ]
    }
  ]
}

我目前的进度:

router.route("/latest-tasks").get((req, res) => {
    Task.find()
        .sort({ date: "desc" })
        .then(doc =>
            res.status(200).json({
                taskId: doc.taskId,
                list: doc.map(doc => {
                    return {
                        username: doc.username,
                        date: doc.date
                    };
                })
            })
        )
        .catch(err => res.status(400).json("Error: " + err));
});

这里有点多查询的场景,建议使用MongoDB聚合来实现。此查询应该有效:

Todo.aggregate([
  {
    $sort: { taskId: 1, date: 1 }
  },
  {
    $group: {
      _id: "$taskId",
      users: {
        $push: { username: "$username", date: "$date" }
      }
    }
  },
  {
    $project: {
      _id: 0,
      taskid: "$_id",
      users: {
          $filter: {
            input: [
              { $arrayElemAt: ["$users", 0] },
              { $arrayElemAt: ["$users", 1] },
              { $arrayElemAt: ["$users", 2] }
            ],
            as: "user",
            cond: { $ne: ["$$user", null] }
          }
        },
    }
  }
]).exec()
.then(doc => { console.log(doc); })
.catch(err => { console.log(err); });

聚合管道说明:

  • $sort:这使用 taskId 和 date 字段按升序对任务进行排序
  • $group:按 taskId 对任务进行分组。这就是我们如何让所有用户与任务相关联
  • $project:这有助于仅提取与任务关联的前 3 个用户。此管道阶段中使用的 $filter 运算符有助于删除空值,以防任务最多没有三个用户与之关联。

链接:Aggregation Pipeline, Pipeline Stages, Pipeline Operators

您需要使用.aggregate:

猫鼬代码未测试

Task.aggregate([
  {
    $sort: {
      taskId: 1,
      date: -1
    }
  },
  {
    $group: {
      _id: "$taskId",
      users: {
        $push: {
          username: "$username",
          date: "$date"
        }
      }
    }
  },
  {
    $facet: {
      tasks: [
        {
          $sort: {
            _id: 1
          }
        },
        {
          $project: {
            _id: 0,
            taskid: "$_id",
            users: 1
          }
        }
      ]
    }
  }
]).exec()
.then( doc => res.status(200).json(doc))
.catch(err => res.status(400).json("Error: " + err));

MongoPlayground