0
votes

I am quite a newbie at Meteor. I naively thought that a "publish" on the server would send across to the client a set/subset of a collection into a synchronised minimongo collection, but more importantly that the subscribed client would only be allowed to deal with that published set of data (no more, no less). However when subscribing inside a template helper, it looks like:

1) you cannot use the name of the 'publish' (what 's its use then?)

2) you have to query the collection and do the filtering again (why then bothering filtering in the 'publish'?)

Here is the code:

meteor:PRIMARY> db.products.insertMany([
... { "name" : "product_1", "color" : "black", "taste" : "salty" }    ,
... { "name" : "product_2", "color" : "black", "taste" : "sweet" }    ,
... { "name" : "product_3", "color" : "white", "taste" : "salty" }    ,
... { "name" : "product_4", "color" : "white", "taste" : "sweet" }  ])

template:

<template name="products">
     <h2> All of them:</h2>
        {{#each allOfThem}}
              <li>
                {{name}} {{color}} {{taste}}
              </li>
        {{/each}}
     <h2> salty ones:</h2>
        {{#each saltyOnes}}
              <li>
                {{name}} {{color}} {{taste}}
              </li>
        {{/each}}
</template>

in main.js - server:

Meteor.startup(() => {
    Meteor.publish('saltyProducts', function(){
    return Products.find( { taste : "salty"} );
    });
});

in main.js - client:

Template.products.onCreated( function() {
    Meteor.subscribe("saltyProducts");
});
Template.products.helpers({
    allOfThem: function(){
        return Products.find( {});
    },
    saltyOnes: function(){
       return Products.find( { taste : "salty"} );
    }   
});

and the result:

All of them, instead of my subscription..
product_1 black salty
product_2 black sweet
product_3 white salty
product_4 white sweet

salty ones, but I had to filter in the helper..
product_1 black salty
product_3 white salty

Of course I have tried to do: return saltyProducts.find( {} ); but that does not work. Again, what's the point having defined the "saltyProducts" publication?

2
Have you turned off autopublish package? Since if this is the only publication you have on server, then, unless autopublish package is enabled, you shouldn't have got all the products, just salty ones, which you published. - Artūrs Lataks
Thanks a ton Artus, you made my day! - Jalmince
However 1 minor question remains: what is the use of that name "saltyProducts" I gave to the publication ? ( since in the client/template/helper I still have to subscribe to "Products", which now represents the reduced set ) - Jalmince
@Jalmince, i updated my answer to help answer this for you. - zim
@Jalmince saltyProducts is the name of your publication. Like an identifier for a dataset you will return from your .publish() method. It is for your information, like which dataset you want to receive when you call .subscribe() - Artūrs Lataks

2 Answers

1
votes

you're heading down a road where you're going to run into the Meteor mergebox. when you publish items to a collection name, they are merged with any other items already published to that collection name.

for example, you can publish your salty items to the products collection, but once you publish, say, "just" the sweet items, both the salty and sweet are published to the client.

in this scenario, yes, you are right that you have to then further filter on the client. you are filtering on the set of items that have been published, and not the set of items in the database.

there are ways around this. you can define a client-side collection called "saltyItems" and publish a subset of products into that. i've done that when using a package called publish-composite:

https://github.com/englue/meteor-publish-composite

though composite publishing may be more than you need here, it does allow you to define the name of an ad hoc collection, which you can then define on the client in order to do a find on that specific set of published data.

edit:

you're asking about doing a client-side find on Products, vs "saltyProducts". Products is a variable you've (likely) set up when you defined the collection, and it's tied to the collection "products" (i assume). whereas "saltyProducts" is merely the name of the publish.

but you can create an ad-hoc client-side collection called "SaltyProducts", if you would like, like this:

const SaltyProducts = new Meteor.Collection('saltyProducts');

you can subscribe in a template like this:

this.subscribe('saltyProducts');

... and you can find in a helper like this:

return SaltyProducts.find({});

and though that may look like exactly what you want, it really isn't. because the result of the publisher you wrote will still put the results in the collection called "products".

i reckon there are other ways around this, but the package i mentioned above will allow you to publish a subset of all your products (i.e. the salty ones) into whatever you want to call the collection ("saltyProducts").

then, on the client, you will be able to do the find() you expect to do, and get the results you expect.

0
votes

Have you turned off autopublish package? Since if this is the only publication you have on server, then, unless autopublish package is enabled, you shouldn't have got all the products, just salty ones, which you published.