Skip to content
This repository has been archived by the owner on Jun 29, 2021. It is now read-only.

Filter documents by subscription (a.k. find from publication) #183

Open
SimonSimCity opened this issue Sep 20, 2017 · 1 comment
Open

Filter documents by subscription (a.k. find from publication) #183

SimonSimCity opened this issue Sep 20, 2017 · 1 comment

Comments

@SimonSimCity
Copy link

SimonSimCity commented Sep 20, 2017

In my current project, I have multiple subscriptions, publishing their content to the same collection on the client side (since they are also managed on the same collection on the server side). This problem is also noted here: https://www.discovermeteor.com/blog/pagination-problems-meteor/#problem-2:-subscription-ownership

Currently I've found two possible solutions to this problem:

  1. Publishing the metadata in a second collection and join them on the client,
    as percolate:find-from-publication does it. While the idea is good and the approach is very clean, it can be very slow on your client.

  2. Adding a custom field to the document when publishing, as peerlibrary:subscription-scope does it. This plugin seems like having a very neat and effective approach, but doesn't work with reywood:publish-composite.

In my opinion, Meteor should natively provide a solution for this problem.

I want it now. What can I do?

  1. Install reywood:publish-composite and use it for all your publications.
  2. The options-parameter of your cursor, returned in the publication, you should include a transformator that adds a property, specific for this publication.
  3. In your collection you should define a transformator that removes this property.

What happens here in detail?

When publishing your documents, Meteor will use the transformator, specified in your cursor, to add this field. When fetching the documents on the client side it will remove this field. The transformation will also take place when fetching documents on the server, but without effect. This might throttle your performance a tiny bit 😜

Why do I need reywood:publish-composite?

You can find an explanation in the issue 28 of their repository or in this post.

Give me an example please.

const Posts = new Mongo.Collection('posts', {
  transform: (doc) => {
    delete doc._publications_latest_posts;
    return doc;
  },
});

if (Meteor.isServer) {
  Meteor.publishComposite('latest_posts', (selectors, options) => {
    const definition = {
      find() {
        options.transform = (doc) => {
          doc._publications_latest_posts = true;
          return doc;
        };

        return Posts.find(selectors, options);
      },
    };

    return definition;
  });
}

if (Meteor.isClient) {
  Meteor.subscribe('latest_posts', { deleted: false }, { limit: 10 }, { onReady: () => {
    // Will only find posts, published by the 'latest_posts' publication.
    Posts.find({
        _publications_latest_posts: true,
      }, {
        sort: { createdAt: -1 },
      });
  } });
}

The only strange thing though: You're querying for a field on the client that you'll never see after you fetched the documents ...

What's the downside of this solution?

As you define a transformator, you can't use other plugins that also want to set it, since only one transformator can be defined for a collection or query. This makes this solution incompatible f.e. with dburles:collection-helpers. Dropping the collection helper will enable this again, but will also return the extra field when you query the collection. If you use dburles:collection-helpers, take a look at this comment on their repository.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants