A question on the separation of client and server

I have a collection that looks as follows:

{
  "_id": "1234",
  "battletag": "player#1234",
  "games": [{
    "gameId": "5678",
    "characters": ["corvid", "crow"]
  }, {
    "gameId": "1267",
    "characters": ["jackdaw", "magpie"]
  }]
}

I often have routes that have the prefix of /games/:gameId, where any players have their games array limited to what is currently in the route parameters (both security and convenience).

Meteor.publish('player', function (playerId, gameId) {
  return Players.find({
    "_id": playerId,
    "games.gameId": gameId
  }, {
    fields: {
      "games.$": 1
    },
    $slice: 1
  });
});

Of course, on the client this will mean I get back a single game from my collection.

What I am wondering is, what happens when you try to update this on the client? That is, you’re only getting one field back. If you try to update games.0.characters, is it smart enough to update the correct game?

I am using autoform, so it often tries to update games.0.characters.

I would say the answer is no. If you look on the Mongo docs you will see the following operators

$addToSet	Adds elements to an array only if they do not already exist in the set.
$pop            Removes the first or last item of an array.
$pullAll	Removes all matching values from an array.
$pull	        Removes all array elements that match a specified query.
$pushAll	Deprecated. Adds several items to an array.
$push	        Adds an item to an array.

What i have done in a similar situation is remove the existing object via Players.update({ _id:._id }, { $pull: { "games": game } });

and then right afterwards insert the modified data using Games.update({ _id : this._id }, { $addToSet : { 'games' : game } });

1 Like

Yeah that’s what I was thinking to do, it just seems so messy, but I guess it works.

Meteor publications work by setting up an observer on the cursor. You can actually setup this scenario manually, which I demonstrate in some demo code I wrote for a presentation I gave. In the subNullDemo app I simulate a regular collection on the Client, but the server is actually just a null-named collection not even backed by MongoDB. All updates from the client get handled just as you would expect because I mocked up the required Meteor.method calls on the server.

The point is, it would be easy to determine if Meteor would indeed handle the situation you describe above. Open up your client using Chrome (or some other browser that can monitor websockets) and see what happens when you update the data in MongoDB. If you see an update message from the server to the client that updates the correct data, then your answer is “yes, meteor will handle this scenario”. If you do not see a websocket message from the server updating the collection, then the answer is “no”.

My gut feeling is that it will indeed work. My thought is that it would work because the action you describe seems to update the results of the cursor, which is what Meteor is monitoring. Once the results of the cursor is updated, the observer-pattern used all over Meteor will take care of updating the data accordingly. I would be interested to see what experimentation showed, however.

1 Like