Mongodb,猫鼬-使用汇总和分组按_id和日期排序

时间:2020-03-21 16:53:47

标签: node.js mongodb sorting mongoose aggregation-framework

我正在尝试按task._iddate的降序排列。我可以按task._id进行排序,但不能按date进行排序,我尝试更改顺序仍然没有任何运气。我得到了响应,但只是集合了用户任务的顺序,而不是usertask.date

  1. 用户(姓名,地址等)
  2. 任务(名称,图标,受让人)
  3. UserTask(User.ObjectId,Task.ObjectId,日期)

用户集合:

{
    "users": [
        {
            "name": "Bill",
            "phone": "345"
        },
        {
            "name": "Steve",
            "phone": "123"
        },
        {
            "name": "Elon",
            "phone": "567"
        }
    ]
}

任务集合:

{
    "tasks": [
        {
            "name": "Run 100m",
            "icon": "run",
            "assignee": "Elon"
        },
        {
            "name": "Walk 1 hour",
            "icon": "walk",
            "assignee": "Bill"
        },
        {
            "name": "Jog 30 minutes",
            "icon": "jog",
            "assignee": "Steve"
        }
    ]
}

用户任务:

    {
        "_id": "5e72fec..",
        "user": "5e72fa4..",
        "task": "5e72fbac..",
        "date": "2020-03-03T05:10:10.000Z",
        "createdAt": "2020-03-19T05:10:37.027Z",
        "updatedAt": "2020-03-19T05:10:37.027Z",
        "__v": 0
    },
    {
        "_id": "5e72fed3..",
        "user": "5e72fa4e..",
        "task": "5e72fbac..",
        "date": "2020-03-12T05:10:10.000Z",
        "createdAt": "2020-03-19T05:10:43.296Z",
        "updatedAt": "2020-03-19T05:10:43.296Z",
        "__v": 0
    },
    {
        "_id": "5e72fed6..",
        "user": "5e72fa..",
        "task": "5e72fb..",
        "date": "2020-03-15T05:10:10.000Z",
        "createdAt": "2020-03-19T05:10:46.057Z",
        "updatedAt": "2020-03-19T05:10:46.057Z",
        "__v": 0
    },
    {
        "_id": "5e72feda...",
        "user": "5e72fa4..",
        "task": "5e72fb..",
        "date": "2020-03-07T05:10:10.000Z",
        "createdAt": "2020-03-19T05:10:50.785Z",
        "updatedAt": "2020-03-19T05:10:50.785Z",
        "__v": 0
    }

这是需要更改的汇总

    UserTask.aggregate([
    {
        $lookup: {
            from: "tasks",
            localField: "task",
            foreignField: "_id",
            as: "matchedTask"
        }
    },
    {
        $unwind: "$matchedTask"
    },
    {
        $lookup: {
            from: "users",
            localField: "user",
            foreignField: "_id",
            as: "matchedUser"
        }
    },
    {
        $unwind: "$matchedUser"
    },
    {
        $group: {
            _id: "$matchedTask._id",
            name: {$first: "$matchedTask.name"},
            icon: {$first: "$matchedTask.icon"},
            assignee: { $first: "$matchedTask.assignee" },
            userdata: {
                $push: {
                    name: "$matchedUser.name",
                    date: "$date"
                }
            }

        }
    },
    {
      $sort: { _id: 1, "userdata.date": -1 }
    }
  ])

.exec()
.then(doc => res.status(200).json(doc))
.catch(err => res.status(400).json("Error: " + err));

响应如下所示,请注意usertask.date。它没有排序

{
        "_id": "5e...",
        "name": "Run 100m",
        "icon": "run",
        "assignee": "Elon",
        "userdata": [
               {
                "name": "Elon",
                "date": "2020-03-21T20:02:38.143Z"
            },
            {
                "name": "Bill",
                "date": "2020-03-11T20:02:38.000Z"
            },
            {
                "name": "Steve",
                "date": "2020-03-19T20:02:38.000Z"
            }
        ]
    }

如您所见,它没有按日期排序-降序排列。结果应如下所示

"userdata": [
               {
                "name": "Elon",
                "date": "2020-03-21T20:02:38.143Z"
            },
            {
                "name": "Steve",
                "date": "2020-03-19T20:02:38.000Z"
            },
            {
                "name": "Bill",
                "date": "2020-03-11T20:02:38.000Z"
            }
        ] 

2 个答案:

答案 0 :(得分:0)

$ sort将使用从聚合管道中出来的最后一个对象,并且该对象中没有字段“ date”:

 {
        $group: {
            _id: "$matchedTask._id",
            name: {$first: "$matchedTask.name"},
            icon: {$first: "$matchedTask.icon"},
            assignee: { $first: "$matchedTask.assignee" },
            userdata: {
                $push: {
                    name: "$matchedUser.name",
                    execDate: "$date"
                }
            }

        }
    },

您的组必须返回一个名为date的字段才能对其进行排序

{
   $group: {
      _id: "$matchedTask._id",
      name: ....,
      date: ....
   }
}
{ $sort: {date: -1}}

如果要排序的值包含另一个对象,则必须在排序时指定它:

{$sort: {"userdata.date": -1}}

答案 1 :(得分:0)

我修复了它,不得不使用两次,现在我可以根据需要获得结果

下面提供的解决方案

UserTask.aggregate([
        {
          $lookup: {
            from: "tasks",
            localField: "task",
            foreignField: "_id",
            as: "matchedTask"
          }
        },
        {
          $unwind: "$matchedTask"
        },
        {
          $lookup: {
            from: "users",
            localField: "user",
            foreignField: "_id",
            as: "matchedUser"
          }
        },
        {
          $unwind: "$matchedUser"
        },
        {
          $sort: { date: -1 }
        },
        {
          $group: {
            _id: "$matchedTask._id",
            name: { $first: "$matchedTask.name" },
            icon: { $first: "$matchedTask.icon" },
            assignee: { $first: "$matchedTask.assignee" },
            userdata: {
              $push: {
                name: "$matchedUser.name",
                execDate: "$date"
              }
            }
          }
        },
        {
          $sort: { _id: 1 }
        }
      ])
        .exec()
        .then(doc => res.status(200).json(doc))
        .catch(err => res.status(400).json("Error: " + err));