重叠的流星出版物

Overlapping Meteor publications

我有一个 meteor 应用程序,它有 2 个发布的帖子。一个用于所有帖子,一个用于精选帖子。有 2 个精选帖子 - "Post 1" 和 "Post 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

它在 "posts" 中显示 "post 1",这是特色但不应出现在第 2 页上。当我转到第 3 页时,我看到 "post 1" 和 "post 4" 但他们不应该在那里。

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

如果我理解正确,您的页面对应于您的 "All Posts" 列表的分页。 "page" 号码作为您的订阅参数发送,以便您收到您的帖子的简短列表。

这里的困难确实是你的客户集合没有你手头的所有文件(因为你在你的 'posts' 出版物中限制了它们),所以你不能使用类似的 skip 逻辑在出版物中。

如 Meteor Guide 中所提议 > Paginating subscriptions, you could use the 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)
});

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

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

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