【问题标题】:Merging collections in Meteor在 Meteor 中合并集合
【发布时间】:2014-01-23 00:01:06
【问题描述】:

假设您希望在单个社交新闻提要上显示多个集合,例如 PostsUsers(新注册)。您将如何在按创建日期排序的列表中反应性地显示两者?

想法 1 - 在客户端合并

您分别发布实体,并在客户端中按日期对每个实体进行排序,然后将它们合并到一个排序数组中,然后将其显示在 {{#each}} 迭代器中。 问题: AFAIK 这需要将响应式光标展平为静态数组,因此现在页面不会更新。 (也许有一种方法可以让页面在任何集合发生变化时重新计算这个数组,从而挽救这种方法?)

想法 2 - 创建一个新集合

您创建了一个新集合,例如FeedItems。在创建新的PostUser 时,您还可以创建一个新的FeedItem 并将相关信息复制到其中。现在在客户端中显示项目非常简单。 问题:现在规范对象和它们的FeedItem 版本之间没有反应,所以如果有人更改他们的名字、删除帖子等,这将不会反映在提要中. (也许有一种方法可以在集合之间创建反应性来挽救这种方法?)

想法 3 - 在出版物中合并

也许有一些方法可以坚持现有的集合,但创建一个额外的'newsFeed' 发布,以某种方式合并它们。但是,我还没有看到任何这样做的方法。我在文档中看到您可以发布一系列集合,但是 AFAIK 这相当于一次发布相同的集合。

这些方法之一是否在正确的轨道上?或者还有其他我没有想到的?

【问题讨论】:

    标签: meteor


    【解决方案1】:

    到目前为止,最简单的解决方案是将它们合并到客户端的模板助手中。例如:

    Template.dashboard.helpers({
      peopleAndPosts: function() {
        var people = People.find().fetch();
        var posts = Posts.find().fetch();
        var docs = people.concat(posts);
        return _.sortBy(docs, function(doc) {return doc.createdAt;});
      }
    });
    

    和模板(假设人员和帖子有name):

    <template name="dashboard">
      <ul>
        {{#each peopleAndPosts}}
        <li>{{name}}</li>
        {{/each}}
      </ul>
    </template>
    

    这个是反应式的,因为帮助器是一个反应式上下文,所以对PeoplePosts 的任何更改都会导致返回的数组被重新计算。请注意,由于您没有返回游标,因此对任一集合的任何更改都将导致整个集合再次呈现。如果返回数组的长度比较短,这没什么大不了的。

    【讨论】:

    【解决方案2】:

    想法 1 似乎开箱即用。我创建了一个新的流星项目并将其更改如下:

    test.js:

    Users = new Meteor.Collection("users");
    Posts = new Meteor.Collection("posts");
    
    if (Meteor.isClient) {    
      Template.hello.array = function () {
          var a = Users.find().fetch()
              .concat(Posts.find().fetch());
          return _.sortBy(a, function(entry) { return entry.votes; });      
      };
    }
    
    if (Meteor.isServer) {
      Meteor.startup(function () {
          // code to run on server at startup
          Users.insert({name: "user1", votes: 1});
          Users.insert({name: "user2", votes: 4});
          Users.insert({name: "user3", votes: 8});
          Users.insert({name: "user4", votes: 16});
    
          Posts.insert({name: "post1", votes: 2});
          Posts.insert({name: "post2", votes: 4});
          Posts.insert({name: "post3", votes: 6});
          Posts.insert({name: "post4", votes: 8});
    
      });
    }
    

    test.html:

    <head>
      <title>test</title>
    </head>
    
    <body>
      {{> hello}}
    </body>
    
    <template name="hello">
      {{#each array}}
      <div>{{votes}} {{name}}</div>
      {{/each}}
    
    </template>
    

    这给出了预期的列表:

    1 user1
    2 post1
    4 user2
    4 post2
    6 post3
    8 user3
    8 post4
    16 user4
    

    然后我在控制台中做了Users.insert({name: "new", votes: 5} 并得到(反应性地):

    1 user1
    2 post1
    4 user2
    4 post2
    5 new
    6 post3
    8 user3
    8 post4
    16 user4
    

    【讨论】:

    • 如果集合中的文档与_id 冲突(相同)怎么办?
    • 没关系。它们永远不会一起存储在同一个集合中。
    【解决方案3】:

    我遇到了这个问题,我想知道混合解决方案是否会更好(或至少更有效):

    David 提出的解决方案效果很好,但正如他所说,在处理大集合时可能会出现问题。

    如何保持本地集合(仅在客户端中),在创建模板时将两个集合合并到本地集合中,然后注册一个观察者(或者每个远程集合的观察者)以使本地集合保持最新?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-27
      • 2015-10-30
      • 1970-01-01
      • 1970-01-01
      • 2016-11-13
      • 1970-01-01
      • 1970-01-01
      • 2013-11-23
      相关资源
      最近更新 更多