【问题标题】:How to populate Comment count to an Item list?如何将评论计数填充到项目列表中?
【发布时间】:2013-05-04 00:00:45
【问题描述】:

我的应用中有两个模型:Item 和 Comment。一个 Item 可以有许多 Comments,一个 Comment 实例包含对带有 key 'comment' 的 Item 实例的引用,以跟踪关系。

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

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

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

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

【问题讨论】:

    标签: node.js mongodb express mongoose


    【解决方案1】:

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

    findAndModify

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

    示例

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

     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: Update Operators

    【讨论】:

    • 感谢@Tilo 的回答。您的技术建议我向我的项目模型添加一个新参数“commmentCount”,并在向项目添加新评论时更新它。虽然这种方法看起来很实用,但我想知道是否有一种方法可以即时计算 commentCount 并将其附加到 Item 模型而无需存储/更新它。
    • 当然,您也可以获取comments 数组并使用它的大小
    • 是的,但是你看我需要传递一个数组项,每个项都有自己的commentCount。有没有办法做到这一点?
    【解决方案2】:

    我对这个问题做了一些研究,并得出了以下结果。首先,MongoDB 文档suggest

    一般来说,在以下情况下使用嵌入式数据模型:

    • 实体之间存在“包含”关系。
    • 您有一对多的关系,其中“许多”对象始终与其父文档一起出现或在其父文档的上下文中查看。

    所以在我的情况下,如果将Comments 嵌入到Items 中,而不是独立存在,则更有意义。

    不过,我很想知道解决方案,而无需更改我的数据模型。正如 MongoDB 文档中的 mentioned

    引用提供了比嵌入更大的灵活性;然而,为了 解决引用,客户端应用必须发出后续 查询。换句话说,使用引用需要更多的往返 服务器。

    由于现在多次往返都是犹太洁食,我想出了以下解决方案:

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

    同意吗?不同意?请用你的 cmets 赐教!

    如果您有更好的答案,请在此处发布,如果我觉得值得,我会接受。

    【讨论】:

      猜你喜欢
      • 2020-04-17
      • 1970-01-01
      • 2019-09-21
      • 2020-09-01
      • 2020-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多