Search code examples
reactjsmeteormeteor-react

Meteor React publish merged collections


With Meteor (1.4.2.3) and React, I have the collection Objects which has an itemId which refers to the collection Items.

Currently I subscribe to the collection on the client side with:

export default createContainer(() => {
  let objectsSub = Meteor.subscribe('allObjects');
  var objects = Objects.find({}, {
      transform: function (doc) {
        doc.item = Items.findOne({
          _id: doc.itemId
        });
        return doc;
      }
    }).fetch();
  return {
    objects: objects,
  }
}, App);

This works perfect, but I think it is more elegant to merge the collections on the server side. However, none of the solutions I found seem to work

Transform at collection definition

const Objects = new Mongo.Collection('objects',
  {
    transform: function (doc) {
      doc.item = Items.findOne({
        _id: doc.itemId
      })
    }
  });

The console gives:

Error: transform must return object

Transform at publish

if (Meteor.isServer) {
  Meteor.publish('allObjects', function () {
    return Objects.find({}, {
      sort: { startedAt: -1 },
      transform: function (doc) {
        doc.item = Items.findOne({
          _id: doc.itemId
        });
        return doc;
      }
    });
  });
};

TypeError: Cannot read property 'name' of undefined

Where name is a property of Items


Solution

  • i usually do it in the publish like this:

      Meteor.publish('allObjects', function () {
        let cursor = Objects.find({}, {
          sort: { startedAt: -1 });
        });
    
        let transformData = (fields) => {
            fields.item = Items.findOne({
              _id: fields.itemId
            });
    
            return fields;
        };
    
        let handle = cursor.observeChanges({
            added: (id, fields) => {
                fields = transformData(fields);
                this.added('objects', id, fields);
            },
            changed: (id, fields) => {
                fields = transformData(fields);
                this.changed('objects', id, fields);
            },
            removed: (id) => {
                this.removed('objects', id);
            }
        });
    
        this.ready();
    
        this.onStop(() => {
            handle.stop();
        });
      }