【问题标题】:Mongoose - Loop an array of embedded docs to .push new value to a field en masse?Mongoose - 循环嵌入文档数组以将新值推送到一个字段?
【发布时间】:2017-06-27 13:22:17
【问题描述】:

我有一个包含一组嵌入式文档(“cmets”)的文档,以及一个如下所示的示例:

{
    "_id" : ObjectId("539e9213209e743d107e7202"),
    "article" : "article1",
    "comments" : [
        {
            "comment" : "comment1",
            "created" : ISODate("2014-06-16T06:43:38Z"),
            "_id" : ObjectId("539e921a209e743d107e7203"),
            "read" : {
                "marked" : false
            },
            "timesent" : {
                "datetime" : "Mon Jun 16 2014 02:43:38 GMT-0400 (EDT)",
                "hour" : 2,
                "minute" : "43",
                "second" : 38,
                "am" : true,
                "month" : 5,
                "day" : 16,
                "year" : 2014
            }
        }
    ]
}

对于 cmets 数组中的每条评论,有没有办法批量更新字段 "read" : {"marked" : true}?

我正在使用 node.js,并且有这样的想法(有问题的部分以

开头

如果 (req.body.readComment) {..

// update the article with this id (accessed by PUT at
// http://localhost:4200/api/v1/articles/:article_id)
.put(function(req, res) {

    Article.findById(req.params.article_id, function(err, article) {

        if (err)
            res.send(err);

        if (req.body.comment) {

            article.comments.push({

                comment : req.body.comment,
                timesent :
                {
                    datetime : req.body.datetimeNow,
                    hour : req.body.hourNow,
                    minute : req.body.minuteNow,
                    second : req.body.secondNow,
                    am : req.body.amNow,
                    month : req.body.monthNow,
                    day : req.body.dayNow,
                    year : req.body.yearNow 
                },
                read :
                {
                    marked : req.body.readComment,
                    datetime : req.body.readCommentDatetime
                },
                created : req.body.datetimeNow

            });

        } // if newComment


    if (req.body.readComment) {

      var comments = // some sort of .find ?
      var embeddedDoc;
      for (var i=0, length=comments.length; i < length; i++){
        embeddedDoc = comments[i];
        embeddedDoc_id = // something to find the embedded doc_id ?
        console.log(i);

                article.comments.push({ // maybe push to the embedded doc_id

                    read :
                    {
                        marked : req.body.readComment,
                        datetime : req.body.readCommentDatetime
                    }

                });

      };

    } // if readComment == true (from ajax .put)


        // save the article, and check for errors
        article.save(function(err) {

            if (err)
                res.send(err);

        res.json({ message: 'Update "' + req.params.article_id });

        });

    });

})

【问题讨论】:

  • 回答中是否有不符合您问题需求的内容?
  • @NeilLunn 不一定.. 数据库发生了一些变化(感谢您的精彩回答),但尚未着手获取 cmets._id,因此尚未对此进行测试..像往常一样,答案似乎很理想,所以接受它是否合适,还是我应该先测试它?刚刚投了赞成票!

标签: javascript node.js mongodb mongoose mongodb-query


【解决方案1】:

由于每个评论都需要在数组中进行标识,因此“批量”一词并不真正适用,因为它们本质上是分开的。至于能够说“更新所有这些'cmets'并将它们标记为true,不直接支持。

但另一方面,您可以通过批量更新操作来简化此操作。因此,对于“评论”_id 值的“列表”,您可以这样做:

var bulk = collection.initializeOrderedBulkOp();

comments.forEach(function(commentId) {
    bulk.find({ "comments._id": commentId }).updateOne({ 
        "$set": { "comments.$.read.marked": false }
    });

    counter++;
    if ( counter % 500 == 0 ) {
        bulk.execute(function(err,result) {
           // do something with the result
           bulk = collection.initializeOrderedBulkOp();
           counter = 0;
        });
    }
});

// Catch any under or over the 500's
if ( counter > 0 ) 
    bulk.execute(function(err,result) {
       // do something with the result here
    });

这至少可以避免您为每个发送到 API 的“评论”_id“通过网络”向服务器实例发送更新。通过对结果进行批处理,可以减少流量并减少等待回调响应的时间。

您可能会使用“异步”来改进此示例,因此即使循环输入列表也是一种非阻塞操作。批处理大小可能会有所不同,但这只是保持在 16MB BSON 硬限制以下的安全示例,因为整个“请求”等于一个 BSON 文档。

【讨论】:

  • 非常酷。谢谢你。关于获取文章文档中每条评论的commentId的任何建议?或者我应该从前端的隐藏字段中获取每条评论的commentId,然后通过ajax 发送?
  • @StackThis 取决于您在客户端中填充数据的方式。如果您只是呈现 HTML,那么隐藏字段似乎是合理的。如果您通过来自 JSON 响应的数据进行渲染,那么应该有一种方法来获取关联的值。真的是另一个问题,实际上取决于您的实施。
猜你喜欢
  • 2015-05-11
  • 2014-12-20
  • 2020-09-11
  • 2020-02-07
  • 2019-11-19
  • 2020-03-27
  • 2020-07-29
  • 2021-03-09
  • 1970-01-01
相关资源
最近更新 更多