Mongoose - 循环一系列嵌入式文档,以便将新值一起推送到一个字段?

时间:2014-06-16 06:57:20

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

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

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

对于comments数组中的每个注释,有没有办法批量更新字段“read”:{“marked”:true}?

正在使用node.js,并考虑到这样的事情(可疑部分以

开头)
  

if(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 });

        });

    });

})

1 个答案:

答案 0 :(得分:2)

因为需要在数组中识别每个注释,所以术语&#34; Bulk&#34;并不真正适用,因为它们本身就是分开的。至于能否只是说&#34;更新所有这些&#39;评论&#39;并将它们标记为true&#34; ,这不是直接支持的。

但另一方面,您可以使用批量更新操作简化此操作。所以对于一个&#34;列表&#34; &#34;评论&#34;您可以执行以下_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
    });

这至少可以避免你通过线路发送更新&#34;每个单独的#34;评论&#34;到服务器实例您发送到API的_id。通过对结果进行批处理,可以减少流量,减少等待回调响应的时间。

使用&#34; async&#34;你可能更好的这个例子因此,即使循环输入列表也是非阻塞操作。批量大小可能会有所不同,但这只是一个安全的例子,可以保持在16MB BSON硬限制之下,因为整个&#34;请求&#34;等于一个BSON文件。