【问题标题】:How to populate lookup result in mongodb?如何在 mongodb 中填充查找结果?
【发布时间】:2021-09-19 02:26:59
【问题描述】:

我有一个评论模型,它的一部分看起来像这样:

const CommentSchema = mongoose.Schema({
    userId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'user',
    },
    contentId: {
        type: String,
    },
    repliedTo: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'comment',
    },
    text: {
        type: String,
        required: true,
    }
});

module.exports = mongoose.model('comment', CommentSchema);

由于我的评论模型是指我的用户模型,这里是它的架构的一部分:

const UserSchema = mongoose.Schema({
    name: {
        type: String,
        required: true,
    },
    email: {
        type: String,
        trim: true,
        unique: 'Email already exists',
        match: [/.+\@.+\..+/, 'Please fill a valid email address'],
        required: 'Email is required',
    },
    photoUrl: {
        type: String,
    },  
    // this will be saved as hashed
    password: {
        type: String,
        required: 'Password is required',
    },
});

module.exports = mongoose.model('user', UserSchema);

当我对帖子发表评论时,会向该帖子添加新评论,但 repliedTo 字段保持为空。 当我回复评论时,它会被视为一条新评论,但这次 repliedTo 字段将引用它正在回复的 comment's _id。

因此,如果对某个内容发表了评论,并且该评论的 id 为“60e70494c3920d001c7fa6d6”,并且如果评论是作为对该评论的回复,则回复的 repliedTo 字段将为“60e70494c3920d001c7fa6d6”

现在,对于某个内容,我想找到在其上制作的 cmets 并回复每个评论;我还必须确保对评论的回复不会显示为独立评论。通过使用 MongoDB 的聚合查询的 $lookup 函数,我可以这样做,这是我的代码:

let comment = await Comment.aggregate([
            [
                {
                    $match: {
                        contentId: req.params.contentId,
                    },
                },
                {
                    $lookup: {
                        from: 'comments',
                        localField: '_id',
                        foreignField: 'repliedTo',
                        as: 'replies',
                    },
                },
                {
                    $match: {
                        repliedTo: {
                            $eq: null,
                        },
                    },
                },
            ],
        ]);
    
const populateQuery = [
            {
                path: 'userId',
                select: '_id name photoUrl',
            },
            
        ];
        
comment = await Comment.populate(comment, populateQuery);

结果:

[
  {
    "_id": "60e70494c3920d001c7fa6d6",
    "text": "This is nice ",
    "contentId": "60c3eda65d90e20008cab22a",
    "userId": {
      "_id": "60b74eea3907f4001c28745c",
      "name": "Meet",
      "photoUrl": "https://images.unsplash.com/photo-1509042239860-f550ce710b93?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80"
    },
    "__v": 0,
    "replies": [
      {
        "_id": "60e705e6c3920d001c7fa6de",
        "text": "I also think this is nice ",
        "contentId": "60c3eda65d90e20008cab22a",
        "userId": "609bf455fcf4e0001c95da59",
        "repliedTo": "60e70494c3920d001c7fa6d6",
        "__v": 0
      },
      {
        "_id": "60e7066fc3920d001c7fa6e4",
        "text": "Yes you are right ",
        "contentId": "60c3eda65d90e20008cab22a",
        "userId": "60b70b79585b8b001c93cdb0",
        "repliedTo": "60e70494c3920d001c7fa6d6",
        "__v": 0
      },
      {
        "_id": "60e7069ac3920d001c7fa6ec",
        "text": "I agree with you all! ",
        "contentId": "60c3eda65d90e20008cab22a",
        "userId": "60b74eea3907f4001c28745c",
        "repliedTo": "60e70494c3920d001c7fa6d6",
        "__v": 0
      }
    ]
  },
  {
    "_id": "60e704a4c3920d001c7fa6dc",
    "text": "This is just more than nice ",
    "contentId": "60c3eda65d90e20008cab22a",
    "userId": {
      "_id": "60b74eea3907f4001c28745c",
      "name": "Meet",
      "photoUrl": "https://images.unsplash.com/photo-1509042239860-f550ce710b93?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80"
    },
    "__v": 0,
    "replies": []
  }
]

从结果中可以看出,每个 comment 中的 userId 都填充了 _id 名称和 photoUrl 但在我的 replies 数组中,userId 只有 _id。

我需要在每个 commentreplies 数组中用 _id 名称和 photoUrl 填充 userId p>

我尝试了很多方法,但找不到解决方案。

请帮我找到解决这个问题的方法。

非常感谢。

【问题讨论】:

    标签: node.js mongodb express mongoose


    【解决方案1】:

    我能够找到解决问题的方法。我在这里分享它,以防将来有人遇到同样的问题:

    let comment = await Comment.aggregate([
                [
                    {
                        $match: {
                            contentId: req.params.contentId,
                        },
                    },
                    {
                        $lookup: {
                            from: 'comments',
                            localField: '_id',
                            foreignField: 'repliedTo',
                            as: 'replies',
                        },
                    },
                    {
                        $match: {
                            repliedTo: {
                                $exists: false,
                            },
                        },
                    },
                    {
                        $lookup: {
                            from: 'users',
                            let: { replies: '$replies' },
                            pipeline: [
                                { $match: { '$expr': { '$in': ['$_id', '$$replies.userId'] } } },
                                { $project: { _id: 0, userId: { _id: '$_id', name: '$name', photoUrl: '$photoUrl' } } }
                            ],
                            as: 'replyUsers',
                        }
                    },
                    {
                        $project: {
                            _id: 1,
                            createdAtTime: 1,
                            contentId: 1,
                            content_type: 1,
                            text: 1,
                            opinions: 1,
                            userId: 1,
                            replies: {
                                $map: {
                                    input: '$replies',
                                    as: "i",
                                    in: {
                                        $mergeObjects: [
                                            '$$i',
                                            {
                                                $first: {
                                                    $filter: {
                                                        input: '$replyUsers',
                                                        cond: { $eq: ['$$this.userId._id', '$$i.userId'] }
                                                    }
                                                }
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    }
                ],
            ]);
    
            const populateQuery = [
                {
                    path: 'userId',
                    select: '_id name photoUrl',
                },
            ];
            // populate the needed fields
            comment = await Comment.populate(comment, populateQuery);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-19
      • 1970-01-01
      • 1970-01-01
      • 2016-02-07
      • 2022-11-30
      • 1970-01-01
      • 2015-03-02
      • 2023-03-12
      相关资源
      最近更新 更多