【问题标题】:Meteor - Display feed of multiple collectionsMeteor - 显示多个集合的提要
【发布时间】:2016-03-23 20:32:56
【问题描述】:

我想显示来自不同集合的项目的提要,按创建日期排序,但我遇到了一些问题。

想要的结果

  • 所有集合中的项目应混合在同一页面上,按日期排序
  • 显示必须保持反应状态
  • 我使用 jQuery Isotope 进行布局
  • 结果集是有限的(例如前 10 个项目),可以单击“加载更多”按钮来扩大查询限制

我无法正确限制结果集

由于每个集合都必须单独查询,我能做的最好的就是获取每个集合的前 10 个项目。

在下图中,所需的结果集是红色的,绿色的轮廓是我得到的。

目前,我获取三个游标,合并到一个数组中,排序并保留前十个。

加载更多内容

单击“加载更多”按钮时,会更新一个反应变量,该变量在订阅中用于限制每个查询的结果。


那种每次都加载太多数据的逻辑感觉很不对劲。对于查询 3000 个元素、将它们排序到数组中并仅首先显示 1000 个元素的页面会有什么性能影响。

我可能忽略了一种非常简单的方法。我相信这里的一些聪明人可以帮助我找到更好的方法。

一些代码

限于两个集合以使其更简洁

// Server
Meteor.publish('allContent', function(limit) {
    return [
        Posts.find({}, {limit: limit}),
        Articles.find({}, {limit: limit})
    ];
});

// Client
Template.home.onCreated(function () {
    var instance = this;

    // initialize the reactive variables
    instance.loaded = new ReactiveVar(0);
    instance.limit = new ReactiveVar(10);

    instance.autorun(function () {

        // get the limit
        var limit = instance.limit.get();

        // subscribe to the posts publication
        var subscription = instance.subscribe('allContent', limit);

        // if subscription is ready, set limit to newLimit
        if (subscription.ready()) {
            instance.loaded.set(limit);
        }
    });

    instance.content = function() {
        var llimit = instance.loaded.get();

        var posts_cursor = Posts.find({}, {limit: llimit});
        var articles_cursor = Articles.find({}, {limit: llimit});

        var posts_docs = posts_cursor.fetch();
        var articles_docs = articles_cursor.fetch();

        var docs = posts_docs.concat(articles_docs);
        var mix = _.sortBy(docs, function(doc) {return doc.created_at;}).reverse().slice(0,Session.get('limit'));

        // Pass the cursors to observe them and re-layout isotope when necessary
        return {items: mix, cursors: [services_cursor, posts_cursor]};
    }

【问题讨论】:

    标签: javascript mongodb meteor


    【解决方案1】:

    这是一个适合您要求的解决方案,但它会给服务器带来更多负载。

    您需要确定出版物中每个集合的限制,并相应地发布它们。假设您的限制设置为 10。

    • 查找并获取每个集合的前 10 个项目。请注意,您可以在此步骤使用的 mongo 请求中按日期对它们进行排序。见herehere
    • 将它们合并到一个数组中,但要跟踪它们的来源。例如,您可以这样做:

      var mergedResults = [];
      _.each( TenLatestPostArray, function( post){
            //we choose the id 1 for the posts
            mergedResults.push({post.createdAt, 1})        
       })
       _.each( TenLatestArticlesArray, function( article){
            //we choose the id 2 for the articles
            mergedResults.push({article.createdAt, 2})        
       })
       //same for your third collection
      
    • 您按日期对mergedResults 进行排序,然后对前 10 个结果进行切片

    • 您从数组中提取 id 并计算结果数组中有多少项来自集合 1、2 和 3
    • 您按照每个集合的特定限制发布它:

      Meteor.publish('allContent', function(limit) {
        return [
          Posts.find({}, {limit: postsLimit}),
          Articles.find({}, {limit: articlesLimit})
        ];
      });
      

    【讨论】:

    • 看起来响应性会丢失,因为发布中不再使用限制参数。正如你所说,性能影响更糟。现在查询量翻了一番。
    • 是的,这不是一个理想的解决方案。您可以使用cursor.observe() 来更新该出版物,但这会使它变得更加矫枉过正。仅供参考,基本逻辑在这里:stackoverflow.com/a/30813050/3793161
    • 或者,您也可以使用github.com/percolatestudio/publish-counts 并在每次收藏数量发生变化时重新订阅。仍然是一个矫枉过正的解决方案,不如前一个可靠
    • 好吧,我已经使用 cursor.observe() 重新布局同位素,但我希望让事情尽可能简单。使用关系数据库,这很常见,我不敢相信没有好的方法可以实现这一目标
    • 是的,聚合 + 反应性并不是一个简单的组合。我通常像你一样通过合并数据客户端来解决这些问题,但我同意这并不令人满意。
    猜你喜欢
    • 1970-01-01
    • 2015-10-30
    • 2015-08-23
    • 2016-06-21
    • 2015-11-03
    • 1970-01-01
    • 1970-01-01
    • 2014-04-18
    • 1970-01-01
    相关资源
    最近更新 更多