【问题标题】:Updating a double nested array MongoDB更新双嵌套数组 MongoDB
【发布时间】:2017-09-11 09:02:00
【问题描述】:

考虑这个架构:

let userSchema = new mongoose.Schema({
id: String,
displayName: String,
displayImage: String,
posts: [
    {
        url: String,
        description: String,
        likes: [String],
        comments: [
            { content: String, date: String, author: { id: String, displayName: String, displayImage: String } }
        ]
    }
]
});

我可以使用这个查询从 cmets 数组中删除某个项目

controller.deleteComment = (req, res, next) => {
User.findOneAndUpdate(
    { id: req.query.userid, 'posts._id': req.params.postid, },
    {
        $pull: {
            'posts.$.comments': { _id: req.body.commentID },
        }
    }
)
    .exec()
    .then(() => {
        res.send('deleted');
    })
    .catch(next);
};

我是否可以使用$set 运算符更新 cmets 数组中的元素?我需要根据评论 ID 更改评论的内容。像这样:

controller.editComment = (req, res, next) => {
    User.findOneAndUpdate(
        { id: req.query.userid, 'posts._id': req.params.postid, 'comments._id':req.body.commentID },
        {
            $set: {
                'posts.$.comments': {  content: req.body.edited },
            }
        }
    )
        .exec()
        .then(() => {
            res.send('deleted');
        })
        .catch(next);
};

这个 ^ 显然不起作用,但我想知道是否有办法做到这一点?

更新 根据下面的建议,我正在执行以下操作来仅管理一个架构。这可行,但是无论我正在编辑哪些帖子 cmets,都只会更新第一个帖子的 cmets。我已经检查过了,返回的文档总是正确的。 doc.save()方法一定有问题。

controller.editComment = (req, res, next) => {
User.findOne(
    { id: req.query.userid, 'posts._id': req.params.postid },
    { 'posts.$.comments._id': req.body.commentID }
)
    .exec()
    .then((doc) => {
        let thisComment = doc.posts[0].comments.filter((comment) => { return comment._id == req.body.commentID; });
        thisComment[0].content = req.body.edited;
        doc.save((err) => { if (err) throw err; });
        res.send('edited');
    })
    .catch(next);
};

【问题讨论】:

    标签: node.js mongodb mongoose nested-documents


    【解决方案1】:

    我不知道实现目标的简单(甚至是艰难的:P)方法。在 mongo 中,双重嵌套数组的操作相对困难,因此最好避免。

    如果您仍然愿意更改架构,我建议您为 cmets 创建一个不同的架构,并在用户架构中引用该架构。

    所以您的评论架构将如下所示:

    let commentSchema = new mongoose.Schema({
         content: String, 
         date: String,
         author: { 
              id: String,
              displayName: String,
              displayImage: String
         }
    });
    

    你的用户架构应该是这样的:

    let userSchema = new mongoose.Schema({
         id: String,
         displayName: String,
         displayImage: String,
         posts: [{
            url: String,
            description: String,
            likes: [String],
            comments: [{
                type: Schema.Types.ObjectId,
                ref: 'comment'   //reference to comment schema
            }]
        }]
    });
    

    这样你的数据操作会容易很多。您可以在获取用户文档时populate cmets。并且,请注意更新/删除操作是多么容易,因为您已经知道要更新的 cmets 的 _id。

    希望这个答案对您有所帮助!

    【讨论】:

    • 通过为帖子建立一个架构来进一步拆分它可能是个好主意。
    • 我明白,但我最初想只使用一个 Schema 来完成这个项目(可能是因为我疯了)有没有办法只用一个 Schema 来做到这一点?
    • 是的,可以在一个模式中管理它。在这种情况下,您必须运行一个 for 循环并将 comments 数组中每个对象的 _idreq.body.commentID 匹配。这很讨厌,但只要数组的长度很小,你会没事的。
    • @AnkitGomkale 我听从了你的建议,一切似乎都在工作,直到我遇到了一个大问题。这是我最终做的事情,但是由于某种原因,它只更新了第一个 POST 的评论。我认为关于doc.save() 有一些我不明白的地方。请看上面,我已经更新了。
    • 也许是因为您这样做只是为了第一次发帖:let thisComment = doc.posts[0].comments.filter((comment) => { return comment._id == req.body.commentID; })。你怎么确定你正在寻找的评论在post[0] 中?我认为您需要为每条评论循环每条帖子:forEach(post) { forEach(comment){ if(comment id match){ update comment} }}。循环完成后,您可以保存文档。或者嵌套的 forEach() 可能会导致异步问题,并且您最终可能会在嵌套的 forEach() 完成之前保存文档。在这种情况下,请在每个循环中保存 doc。告诉过你这会很糟糕:D`
    【解决方案2】:
    controller.editComment = (req, res, next) => {
        User.findOneAndUpdate(
            { id: req.query.userid, 'posts._id': req.params.postid, 'comments._id':req.body.commentID },
            {
                $push: {
                    'posts.$.comments': {  content: req.body.edited },
                }
            }
        )
            .exec()
            .then(() => {
                res.send('deleted');
            })
            .catch(next);
    };
    

    【讨论】:

    • 我想替换评论,而不是推新评论
    猜你喜欢
    • 2019-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-22
    • 1970-01-01
    • 1970-01-01
    • 2018-10-22
    • 2019-06-08
    相关资源
    最近更新 更多