2

我的应用中有两个模型:Item 和 Comment。一个 Item 可以有很多 Comments,一个 Comment 实例包含对 Item 实例的引用,其键为“comment”,以跟踪关系。

现在,当用户在特定 URL 上请求时,我必须发送所有项目的 JSON 列表及其评论计数。

function(req, res){
  return Item.find()
    .exec(function(err, items) {
        return res.send(items);
    });
};

我不确定如何将评论数“填充”到项目中。这似乎是一个常见问题,我倾向于认为应该有一些比蛮力更好的方法来完成这项工作。

所以请分享你的想法。您将如何“填充”项目的评论计数?

4

2 回答 2

0

I did some research on this issue and came up with following results. First, MongoDB docs suggest:

In general, use embedded data models when:

  • you have “contains” relationships between entities.
  • you have one-to-many relationships where the “many” objects always appear with or are viewed in the context of their parent documents.

So in my situation, it makes much more sense if Comments are embedded into Items, instead of having independent existence.

Nevertheless, I was curious to know the solution without changing my data model. As mentioned in MongoDB docs:

Referencing provides more flexibility than embedding; however, to resolve the references, client-side applications must issue follow-up queries. In other words, using references requires more roundtrips to the server.

As multiple roundtrips are kosher now, I came up with following solution:

var showList = function(req, res){

  // first DB roundtrip: fetch all items
  return Item.find()
        .exec(function(err, items) {
            // second DB roundtrip: fetch comment counts grouped by item ids
            Comment.aggregate({
                $group: {
                    _id: '$item',
                    count: {
                        $sum: 1
                    }
                }
            }, function(err, agg){
                // iterate over comment count groups (yes, that little dash is underscore.js)
                _.each(agg, function( itr ){
                    // for each aggregated group, search for corresponding item and put commentCount in it
                    var item = _.find(items, function( item ){
                        return item._id.toString() == itr._id.toString();
                    });
                    if ( item ) {
                        item.set('commentCount', itr.count);
                    }
                });
                // send items to the client in JSON format
                return res.send(items);
            })          
        });

};

Agree? Disagree? Please enlighten me with your comments!

If you have a better answer, please post here, I'll accept it if I find it worthy.

于 2013-05-03T16:00:45.977 回答
0

检查 MongoDB 文档并寻找方法findAndModify()——使用它,您可以自动更新文档,例如添加注释并同时增加文档计数器。

查找并修改

findAndModify 命令以原子方式修改并返回单个文档。默认情况下,返回的文档不包括对更新所做的修改。要返回包含对更新所做的修改的文档,请使用新选项。

例子

使用该update选项,将更新运算符$inc用于计数器,并将$addToSet实际评论添加到嵌入的评论数组中。

 db.runCommand(
            {
              findAndModify: "item",
              query: { name: "MyItem", state: "active", rating: { $gt: 10 } },
              sort: { rating: 1 },
              update: { $inc: { commentCount: 1 }, 
                        $addToSet: {comments: new_comment}  }
            }
              )

看:

MongoDB:findAndModify

MongoDB:更新运算符

于 2013-04-29T01:37:26.530 回答