【问题标题】:Overlapping Meteor publications重叠流星出版物
【发布时间】:2017-10-15 20:24:12
【问题描述】:

我有一个流星应用程序,其中有 2 个帖子出版物。一个用于所有帖子,一个用于特色帖子。有 2 个精选帖子 - “帖子 1”和“帖子 4”。我在所有页面上显示精选帖子,同时按名称对所有帖子(包括精选帖子)进行分页。当我在页面之间旅行时,来自 2 个出版物的数据会混淆并显示不正确的结果。

代码如下:

Meteor.publish('posts', function(page) {
  const skip = parseInt(page && page !== '' ? page : 0) * 3
  return Posts.find({}, {
    limit: 3,
    skip,
    sort: {
      name: 1
    }
  });
});

Meteor.publish('featured', function() {
  return Posts.find({
    featured: true
  }, {
    sort: {
      name: 1
    }
  });
});

在客户端上,我订阅了两者并在 2 个循环中显示数据

Template.hello.onCreated(function helloOnCreated() {
  const instance = this;
  instance.autorun(function() {
    instance.subscribe('posts', FlowRouter.getParam('page'))
    instance.subscribe('featured')
  });
});

Template.hello.helpers({
  posts() {
    return Posts.find({}, {
      limit: 3,
      sort: {
        name: 1
      }
    })
  },
  featured_posts() {
    return Posts.find({
      featured: true
    }, {
      sort: {
        name: 1
      }
    });
  }
});

HTML模板如下:

<template name="hello">
  <h2>Featured</h2>
  {{#each featured_posts}}
    {{> post}}
  {{/each}}
  <h2>Posts</h2>
  {{#each posts}}
    {{> post}}
  {{/each}}
</template>

问题是来自 2 个订阅的数据在显示中混淆了。

第 1 页显示正确:

Page 1

Featured
  post 1
  post 4

All Posts
  post 1
  post 2
  post 3

但是当我转到第 2 页时

Page 2

Featured
  post 1
  post 4

All Posts  -- Should be
  post 1        post 4
  post 4        post 5
  post 5        post 6

它在“帖子”中显示“帖子 1”,这是特色但不应该出现在第 2 页上。当我转到第 3 页时,我看到“帖子 1”和“帖子 4”,但它们不应该在那里.

我了解发布和订阅的工作原理以及发生这种情况的原因 - 因为发布合并了数据集。我想知道是否有办法将它们分开?

【问题讨论】:

    标签: meteor subscriptions meteor-publications


    【解决方案1】:

    如果我理解正确,您的页面对应于“所有帖子”列表的分页。 “页”号作为您的订阅参数发送,以便您收到一个简短的帖子列表。

    这里的困难确实是您的 Client 集合中没有您所有的文档(因为您在 'posts' 发布中限制了它们),因此您不能使用与发布中类似的 skip 逻辑。

    按照 Meteor Guide > Paginating subscriptions 中的建议,您可以使用 percolate:find-from-publication Atmosphere 包轻松检索来自您的 'posts' 出版物的文档,并且只检索它们。

    // Server
    FindFromPublication.publish('posts', function(page) {
      // Same logic
      const skip = parseInt(page && page !== '' ? page : 0) * 3
      return Posts.find({}, {
        limit: 3,
        skip,
        sort: {
          name: 1
        }
      });
    });
    
    // Client (no change in subscription)
    Template.hello.helpers({
      posts() {
          return Posts.findFromPublication('posts', {}, {
            sort: {
              name: 1
            }
          });
        } // (no change in featured_posts)
    });
    

    【讨论】:

      【解决方案2】:

      我建议使用observe or observeChanges,以便可以在客户端上隔离正在发布的数据。文档可能令人生畏,但实际上比看起来要容易。

      只需创建一个特殊的客户端集合,然后在观察回调中使用该集合的名称即可。请注意,客户端集合名称"featured_posts" 用于在发布中对self.addedself.changedself.removed 的调用:

      // client-side
      const FeaturedPosts = new Mongo.Collection('featured_posts', {
        defineMutationMethods: false
      });
      
      // server-side
      Meteor.publish('featured', function() {
          const self = this;
      
          const handle = collection.find(selector, opts).observe({
            added: function(doc) {
              self.added('featured_posts', doc._id, doc);
            },
      
            changed: function(newDoc, oldDoc) {
              self.changed('featured_posts', newDoc._id, newDoc);
            },
      
            removed: function(doc) {
              self.removed('featured_posts', doc._id);
            },
          });
      
          self.ready();
      
          self.onStop(function(err) {
            if (!err) {
              handle.stop();
            }
          });
        });
      };
      

      【讨论】:

      • 我不能肯定地说,因为我不使用集合助手,但考虑到它只是注册一个转换函数,我希望它可以在转换函数工作的任何地方工作,即使用observe。从文档中......“转换不适用于observeChanges的回调或发布函数返回的游标。”
      • 另外...如果您需要“加入”来自其他集合的数据,请记住您可以在回调中执行您需要的任何自定义逻辑。此外,您可以将转换函数传递给 find/findOne 以覆盖集合级别的转换。
      猜你喜欢
      • 1970-01-01
      • 2014-07-24
      • 1970-01-01
      • 1970-01-01
      • 2015-05-02
      • 1970-01-01
      • 2017-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多