Publish to client-side collection without publishComposite?

I quite often use reywood:publish-composite for just one reason: to be able to send a specific sub-set of a collection to a client-only named collection. This works very well.

However, since publishComposite says that it should not be used with large data sets. I am wondering if there’s a better way to do this, if you don’t need any child collection. I mean something like:

Meteor.publish('name', fn(), 'collectionName')

Is there a package that does just this?

New here sort of, since last Spring in the Northwest. Going to try to step up on reply since it has been 5 hours. My perspective is very different from the +decade ninjas.

Is this a design issue perhaps? If it can be shaken out of the design differently, and you think forward 5-10 years unless you plan on the system being EOL before that:

Is this perhaps the time for an agent which is running fn() but in the background all the time? Client would be agnostic and just be using data that was curated by an agent and the server is not the curator. Certainly not “at the point of need” … I feel like there is complexity not being declared and likely other places where this is true. We have that feeling of wanting to continue “what works” and optimize it, but sometimes an overall shift in design becomes possible due to the new landscape, and otherwise it would have cost a fortune.

Now it seems like “large data sets” will cause the old design thinking to “cost a fortune” instead, so the pendulum is swinging in design. And I would love to know more about the actual design situation.

I am not sure I understand your question or how it needs publish-composite. As I understand publish-composite is basically a hack to have joins, why is it needed for client only collection? Maybe you can share how you use it to have better idea?
In any case maybe check redis oplog Vent: redis-oplog/docs/vent.md at master · cult-of-coders/redis-oplog · GitHub - this can be a simple way to have a lot of control and keep things reactive.

Let me explain: publish-composite allows to set a collectionName that is different from the actual server-side collection name. This allows you to send a specific sub-set to a client-only collection with the same name. This is especially handy if you have more than one subscription to the same collection on the same page.

In my main app (marblever.se), we have different feeds, one showing content from your friends, and one showing content nearby (location-based). Typically, they have only few common documents. If we would publish to the same collection, documents from both subs would be mixed up and we would have to separate them on client-side.

It would be nice, if Meteor.publish() would support this by default. Under the hood, it’s pretty trivial, since the DDP messages send the collection name along with the update messages. It does not have to be the same name as on server-side.

The code for your publication becomes a bit more verbose, but it is possible without a package.

const Fruits = new Mongo.Collection('fruits');

Meteor.publish('myApples', function() {
    const userId = this.userId;
    if (!userId) return [];

    const clientCollection = 'apples';

    const cursor = Fruits.find({ type: 'apple' });

    const observerHandle = cursor.observeChanges({
        added: (_id, fields) => {
            // console.log('Added:', _id, fields);
            this.added(clientCollection, _id, fields);
        },
        changed: (_id, fields) => {
            // console.log('Changed:', _id, fields);
            this.changed(clientCollection, _id, fields);
        },
        removed: (_id) => {
            // console.log('Removed:', _id);
            this.removed(clientCollection, _id);
        }
    });

    this.ready();

    // Stop observing the cursor when the client unsubscribes
    this.onStop(() => {
        observerHandle.stop();
    });
});

If you subscribe to this on the client, you’ll be able to access the documents in a collection named “apples”.

5 Likes

I think it would be great if this example by fishsaidno would be added to the docs somewhere close to the added, changed, removed API entries. Currently the description of added, changed, removed is rather cryptic and really requires you to already know what these do. This example nicely teaches the concept in a few lines. Although no idea where exactly this could be added in the docs.

Awesome, I was hoping this was possible using the low-level syntax.

Would love to see a “collectionName” option added to the standard “publish”, though. This would make things much easier.