meteorjs推荐计数大集合的方式取决于价值

时间:2014-06-03 01:15:27

标签: collections meteor

我的meteorJs应用程序中的pge性能有问题。

情况: 我有2个收藏 - 业务 - 分类

商家是具有一个或多个类别的商品。

它的构建如下:

{
  _id : id,
  categories : [catid1, catid2, catid3],
  other data ...
}

在一个页面上,我显示所有类别,并希望显示有多少商家项目具有此类别的ID。我测试了几种方法,以最好的方式做到这一点,但所有方式都有性能问题,所以我正在寻找一种推荐方式。

目前我这样做:

// server
Meteor.publish('allBusiness', function(){
    return Business.find({}, {reactive : false, fields : {_id:1,categories:1}});
});
// client
Meteor.subscribe('allBusiness');

在我的模板中,显示类别,我使用此模板帮助:

// template
<li>{{name /* Name of Category*/}} ({{countBusiness _id/* Id of Category*/}})</li>


// handlebars helper
Handlebars.registerHelper('countBusiness', function(id) {
    return Business.find({ 
    categories : { $in : [id] } 
    }).fetch().length;

});

有&#34;只是&#34;大约1.000个商业项目(略少于1000个),但是我的本地主机需要大约1分钟才能加载,并且当它加载时全部都是滞后的。有没有更好的方法来解决这个问题?

2 个答案:

答案 0 :(得分:2)

如果你真的不想对你的数据进行非规范化,我会选择休伯特的答案。根据{{​​1}}集合的大小,这应该很有效,特别是如果您有Business的索引。缺点是你不断地在你的数据库中找到一个可以预先计算的计数。

另一种方法是在每个categories文档中保留Business个文档的数量。它可以减少数据库负载并可以很好地扩展,但每次修改业务时都需要修改相应的类别。

如果你走这条路线,你可以使用collection-hooks或只是在更新Categories文件时使用方法。

答案 1 :(得分:1)

如果您不需要Business条目的数据,只需要他们的计数,您就不应该订阅它们。这样你就可以将所有数据发送到客户端,这需要时间。

最简单的解决方案是使用以下方法计算服务器上的值:

var counts = {};
var countDep = new Deps.Dependency();

UI.registerHelpers({
  countBusiness: function(id) {
    countDep.depend();
    if(counts[id] === undefined) {
      Meteor.call('countBusiness', id, function(error, result) {
        counts[id] = result;
        countDep.changed();
      });
    }
    return counts[id];
  },
});

现在是服务器方法。在这里,您应该使用.count()而不是.fetch().length,因为后者仍需要时间从数据库中获取所有内容。

Meteor.methods({
  countBusiness: function(id) {
    return Business.find({ 
      categories: id,
    }).count();
  },
});

更好的,反应性的解决方案是创建一个具有每个类别的业务计数的虚拟集合并订阅它。请参阅counts-by-room示例here in the documentation,了解它是如何完成的。