Meteor DDP: How to get notified when a NEW document is added to a Collection
Asked Answered
O

2

6

I am writing a piece of software that connects to a Meteor server via DDP to read data.

The problem I am facing is figuring out how to differentiate between a NEW document getting added to a collection and getting notified about already-existing documents.

When I first connect to the server, I get a series of added messages to populate the clientside collection. I don't know how to differentiate between those messages, and the ones that come later, indicating a new document was added live. This gets even worse when the DDP client needs to reconnect to the server, at which point all of the current documents are again sent as added messages.

Ottilie answered 30/7, 2014 at 19:55 Comment(3)
This is a recurring question. does this solution work for you? #10219034Miles
It's a tad different because that question (and the one it links to) are both talking about writing direct Meteor code rather than using DDP in a client app. But it might be close enough to close as dupe. The bottom line is that it appears what I need to do is handle figuring out the distinction myself in my own code (probably by including a timestamp in new documents). I was hoping for a built-in utility to do it.Ottilie
My gut instinct is to say you should ignore everything that's added before the ready message arrives for that subscription id. I'm pretty sure that this is what fires the Meteor.subscribe callback referred to in the linked^2 example. HOWEVER, I am not convinced that this ready message is actually guaranteed to arrive after all the initial added messages, which means that this technique might not be reliable. Please let me know if you'd like an example and I will happily post. I'd also love to know what MDG suggest!Eliathan
E
10

Took me a while to actually realise, but this is exactly the kind of thing that the low-level publish API is designed for. Read the section from "Alternatively, a publish function can..." downwards, and it should be pretty clear how you only send added messages for genuinely new documents. Or to provide a simple example:

Both server and client:

MyData = new Meteor.Collection("mydata");

Client:

Meteor.subscribe('myPub', myFilter);

Server:

Meteor.publish('myPub', function(filter) {
  var self = this;
  var initializing = true;

  var handle = MyData.find(filter).observeChanges({
    added: function (id, fields) {
      if (!initializing)
        self.added("mydata", id, fields);
    },
    changed: function(id, fields) {
      self.changed("mydata", id, fields);
    },
    removed: function (id) {
      self.removed("mydata", id);
    }
  });
  initializing = false;
  self.ready();

  self.onStop(function () {
    handle.stop();  // v. important to stop the observer when the subscription is stopped to avoid it running forever!
  });
});

UPDATE

This is so fundamental I've actually written a blog post about it.

Eliathan answered 31/7, 2014 at 21:31 Comment(1)
Ah ha! This does seem to be exactly the type of solution I was looking for! I haven't had a chance to try it out yet but I am accepting it as it does clearly seem to be the intended method of accomplishing this.Ottilie
A
3

I have had this problem in the past and found a solution. Set a variable at first render and change the variable after the intial observe - example:

var initializing = true;

var handle = Collection.find().observe({
  added: function (item) {
    if (!initializing)
        // do stuff with newly added items, this check skips the first run
  }
});

initializing = false;
Anjanette answered 31/7, 2014 at 0:35 Comment(1)
Actually, the function is called "observeChanges", and it works like this docs.meteor.com/api/…Crossstaff

© 2022 - 2024 — McMap. All rights reserved.