Mongodb - 由嵌入式文档id聚合覆盖外部文档_id

时间:2015-03-06 20:22:14

标签: node.js mongodb mongoose

我有这种'评论'模式:

{ _id: <comment-id>,
  user: {
    id: { type: Schema.ObjectId, ref: 'User', required: true },
    name: String
  },
  sharedToUsers:          [{ type: Schema.ObjectId, ref: 'User' }],
  repliedToUsers:         [{ type: Schema.ObjectId, ref: 'User' }],
}

我想查询通过以下条件的所有评论:

  1. sharedToUsers数组为空
  2. repliedToUsers数组为空
  3. 但是,我希望结果每个用户只包含1条评论(最新评论)。

    我试图创建这个聚合(Node.js,mongoose):

         Comment.aggregate(
            { $match: { "sharedToUsers": [], "repliedToUsers": [] } },
            {
                $group: {
                    _id: "$user.id",
                    user: { $first: "$user" },
                }
            },
            function (err, result) {
                console.log(result);
                if (!err) {
                    res.send(result);
                } else {
                    res.status(500).send({err: err});
                }
            });
    

    它确实有效,但严重的问题是结果注释_id字段被嵌套用户_id覆盖。

    如何保持聚合工作但不覆盖原始注释_id字段?

    由于

1 个答案:

答案 0 :(得分:3)

好的,我有一个解决方案。

我想要的只是按_id进行分组,但是返回带有_id字段的结果文档(使用$ group运算符时会被覆盖)。

我做的就像wdberkley说的那样,我添加了comment_id:{“$ first”:“$ _id”}然后我不想返回comment_id字段(因为它不适合我的模型)所以我已经创建了一个$ project,它将comment_id放在常规的_id字段中。

这基本上就是它的样子:

Comment.aggregate(
        {
            $match: {
                "sharedToUsers": [], "repliedToUsers": []
            }
        },
        {
            $group: {
                comment_id: { $last: "$_id" },
                _id: "$user.id",
                content: { $last: "$content" },
                urlId: { $last: "$urlId" },
                user: { $last: "$user" }
            }
        },
        {
            $project: {
                _id: "$comment_id",
                content: "$content",
                urlId: "$urlId",
                user: "$user"
            }
        },
        { $skip: parsedFromIndex },
        { $limit: (parsedNumOfComments - parsedFromIndex) },
        function (err, result) {
            console.log(result);
            if (!err) {
                Comment.populate(result, { path: "urlId"}, function(err, comments) {
                   if (!err) {
                       res.send(comments);
                   } else {
                       res.status(500).send({err: err});
                   }
                });
            } else {
                res.status(500).send({err: err});
            }
        });

谢谢wdbkerkley!