【问题标题】:Mongodb, mongoose - Sorting by _id and date using aggregate and groupMongodb,猫鼬 - 使用聚合和组按 _id 和日期排序
【发布时间】:2020-03-22 07:35:10
【问题描述】:

我正在尝试按 task._iddate 按 desc 顺序排序。我可以按task._id 排序,但 sortibg bydate 不起作用,我尝试总体更改顺序仍然没有运气。我得到了回复,但只是 usertasks 的订单被添加到集合中,而不是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"
            }
        ]
    }

如您所见,它不是按日期排序的 - desc 顺序。结果应该如下所示

"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"
            }
        ] 

【问题讨论】:

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


    【解决方案1】:

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

     {
            $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}}
    

    【讨论】:

    • 查看编辑,如果您想使用名为“日期”的字段进行排序,它必须存在于组中(在键中)
    • 我将密钥从 execDate 更改为 date,结果仍然相同,它没有对日期进行排序(请参阅编辑后的问题)
    • 查看编辑,这里的“主键”不是日期,而是它的用户数据,所以要么将“日期”放在主组对象中,要么通过指定日期“用户数据”的路径进行排序。日期”,
    • 更改后结果还是一样,请检查更新的问题,我也提供了结果
    【解决方案2】:

    我修好了,必须使用排序两次,现在我可以得到我想要的结果

    下面提供的解决方案

    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));
    

    【讨论】:

      猜你喜欢
      • 2015-07-27
      • 2013-01-22
      • 2018-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-13
      • 2015-03-28
      • 1970-01-01
      相关资源
      最近更新 更多