Meteor PubSub missunderstanding

Hello everybody
I have a question about how meteor pubsub is working internally.

Imagine we have a Projects collection. It contains documents like this:

{
    _id: "1",
    metadata: {
        createdAt: 121323123,
        someOtherData: "Some Data"
    }
}

We are subscribed to a complete document.

Now we have a method that does the following:

Projects.update("1", { $set: { 'metadata.createdAt': Date.now() } });

I would expect Meteor to send a ddp message via websocket containing something like:

{
    "msg": 'changed',
    "collection": 'projects',
    "id": "1",
    "fields": { "metadata.createdAt": newValue }
}

But it’s instead sending this:

{
    "msg": 'changed',
    "collection": 'projects',
    "id": "1",
    "fields": { 
        "metadata": {
            "createdAt": newValue,
            "someOtherData": "Some Data",
        } 
    }
}

I thought meteor would send a message only for the single path that was changed, but it seems to send a message about the entire subdocument.

If this is so, i don’t see the difference between making a $set: { 'metadata': newObject } and setting only the field as done before.

This is causing problems in the following case. Imagine we have a template that’s rendering a text input showing the data in someOtherData. You can start writing that input and onBlur the data will be saved. But while you are writing, some other method changes the value of createdAt inside metadata. The the local collection is updated again to the values, and because the input is rendering the someOtherData value and depends on that, it will be rerendered and your input will be lost, even if that field was not really changed.

@sashko or anybody, please tell me :smile:

This is the way DDP works - any change in a “nested” property results in the complete top level property being sent.

Yeah but that’s only happening with the latest level. Because if you have metadata.someObject.value and you change that value, it will send a message saying metadata: { someObject: { value, ... } } has changed, but only that someObject key, not all of those that are part of metadata

Here’s what we have about it in the Meteor Guide: https://guide.meteor.com/collections.html#schema-design

I’m surprised that the nested value thing works in some cases, since the DDP protocol pretty specifically says that changes are sent for each top-level field in a document: https://github.com/meteor/meteor/blob/devel/packages/ddp/DDP.md#procedure-2

The fields object, if present, indicates fields in the document that should be replaced with new values. The cleared field contains an array of fields that are no longer in the document.

This implies that receiving a metadata field requires the client to replace the entire field with the received value.

@sashko i’m sorry but i don’t find where is that specified in the document, could you quote it?

Just search for that text in the DDP.md document - it’s in the second bullet under the second bullet under the “Procedure” heading in “Managing Data”

1 Like