Sonne
Sonne

Reputation: 701

Use projection for meteor publish subscribe

I have a UI element framework, that works only with specific data model ( expects an object with "text" key). This is different from the data model that exists in my mongodb. So my first idea was to use a projection and publish it to the listeners.

var db = MongoInternals.defaultRemoteCollectionDriver().mongo.db; db.Element.aggregate({$project: { _id:1, text:"$description"}});

The Problem is that this is not a cursor, but just simple ejson object. What strategy should i use to give the UI framework needed data and to have a reactivity/data binding from both sides.

Upvotes: 0

Views: 283

Answers (1)

bluebird
bluebird

Reputation: 640

In your publication, instead of returning a cursor, you can use the lower level publish api to have finer control over the results.

For instance, when you return a cursor from a publication, Meteor calls the _publishCursor function which looks like this:

Mongo.Collection._publishCursor = function (cursor, sub, collection) {
  var observeHandle = cursor.observeChanges({
    added: function (id, fields) {
      sub.added(collection, id, fields);
    },
    changed: function (id, fields) {
      sub.changed(collection, id, fields);
    },
    removed: function (id) {
      sub.removed(collection, id);
    }
  });

  // We don't call sub.ready() here: it gets called in livedata_server, after
  // possibly calling _publishCursor on multiple returned cursors.

  // register stop callback (expects lambda w/ no args).
  sub.onStop(function () {observeHandle.stop();});

  // return the observeHandle in case it needs to be stopped early
  return observeHandle;
};

So, you can modify your publication, to basically do the same thing, but also publish a text field, which gets its value from the description field, like so:

Given the following collection:

MyCollection = new Mongo.Collection("my_collection");

Your publish function might look like this:

Meteor.publish("myPub", function () {
  var sub = this;
  var observeHandle = myCollection.find().observeChanges({
    added: function (id, fields) {
      fields.text = fields.description;  // assign text value here   
      sub.added("my_collection", id, fields);
    },
    changed: function (id, fields) {
      fields.text = fields.description;  // assign text value here 
      sub.changed("my_collection", id, fields);
    },
    removed: function (id) {
      sub.removed("my_collection", id);
    }
  });

  sub.ready()

  // register stop callback (expects lambda w/ no args).
  sub.onStop(function () {observeHandle.stop();});

};

Upvotes: 1

Related Questions