Understanding of Publish and Subscribe


#1

Hello @all,

I’ve problems with understanding of Publish and Subscribe. I’ve the following collections on the server:
Persons --> male and female
Addresses --> Addresses of the Persons

‘Addresses’ Collection has in each item the _id of the ‘Persons’ item, like so:

‘Persons’ Collection: {firstname: ‘Alex’, lastname: ‘Maier’, gender: ‘male’}
‘Addresses’ Collection: {userId: [Persons._id], street: ‘Examplestreet 1’, town: ‘Exampletown’}

The ‘Persons’ publish function look like so:
Meteor.publish(‘persons’, function() {return Persons.find({gender: ‘male’}); );

Now the question:
How should I wirte the Meteor.publish for the ‘Addresses’ Collection if I want to publish the Addresses according to “Persons.find({gender: ‘male’})”?


#2

You may have simplified your example for your question, but I would first consider denormalising your collections. In other words, keep all data for a person (name and address) together in the same document in a single collection.

This strategy will make your find trivial.


#3

ok my simplified example is:

‘Persons’ Collection:
{name: ‘Alex’,
gender: ‘male’},
{name: ‘Sam’,
gender: ‘male’},
{name: ‘Anna’,
gender: ‘female’}

‘Addresses’ Collection:
{userId: [Alex]_id,
town: ‘Stuttgart’},
{userId: [Sam]_id,
town: ‘Munich’},
{userId: [Anna]_id,
town: ‘Frankfurt’}

I don’t want to denormalize my collections. It is a example to understand how to do something like this.


#4
Meteor.publish('adressesOfMalePersons', function() {
  var maleIdCursor = Persons.find({ gender: 'male' }, { fields: { _id: 1 } });
  var maleIdArray = maleIdCursor.map(function(p) { return p._id; });
  return Addresses.find({ userId: { $in: maleIdArray } });
});

Notice that the above is not reactive, i.e. if a new male person is added to Persons, the corresponding address is not published. To see how to implement a reactive join, see here.


#5

Try to use publish-composite

Meteor.publishComposite 'persons',  ->
@unblock()
{
	find: ->
		Persons.find({gender: 'male'})

	children: [ { find: (persone) ->
		Addresses.find userId:persone._id
	}]
}

#6

I guess @robfallows is right - it’s a mongo-way and its much better to fetch the data from single collection. I agree that working with nested properties is painfull but you could write a simple interface to deal with nested adddress on the client or server side


#7

Ok, thank you. I will try out your proposals.


#8

It works, super. Many thanks.