mongodbmeteorpublish-subscribesubdocumentminimongo

Meteor/Mongodb - arrays, subdocuments & overlapping subscriptions


I'm making a game; players form leagues and make competing predictions. A league looks like this:

{ leagueName: "Premier League", 
players:[ 
         {name: "Goodie", secretPrediction: "abc"}, 
         {name: "Baddie", secretPrediction: "def"} 
        ] }

For each player, I need to publish to the client the names of all the players in the league, but only their own secret prediction. So from above, if Goodie is logged in, the document on mini-mongo should be:

{ leagueName: "Premier League", 
  players:[ 
           {name: "Goodie", secretPrediction: "abc"}, 
           {name: "Baddie"} 
          ] }

To do this, I have two publications - one to get the whole League document but excluding ALL secret predictions, and one to get the current player's subdocument in the players array including her secret prediction. My publications are:

// Publish whole players array excluding secretPrediction
Leagues.find({"players.name": "Goodie"}, {fields: {"players.secretPrediction": 0}})

// Publish the whole Goodie item in the players array and nothing else 
Leagues.find({"players.name": "Goodie"}, {fields: {players: {$elemMatch: {name: "Goodie"}}}})

The problem is that when I subscribe to both the above publications, I don't get the document I want - the secret prediction is excluded even with the second publication. (On their own, the publications behave as expected, it's only when I subscribe to both.)

Now, I understand from this answer that the two publications should be "merged" on the client

Down to the level of top level fields, Meteor takes care to perform a set union among documents, such that subscriptions can overlap - publish functions that ship different top level fields to the client work side by side and on the client, the document in the collection will be the union of the two sets of fields.

So I have two main questions (and well done / thanks for making it this far!):

  1. Is the union of documents not happening because I'm not dealing with top level fields? Is there a way around this?
  2. Am I going about this completely the wrong way? Is there a better way to get the results I want?

Solution

  • Could you instead rearrange the data document so that you can use a single query e.g.

    { leagueName: "Premier League", 
    players:[ 
             {name: "Goodie"}, 
             {name: "Baddie"} 
            ] 
    playerPredictions:[ 
             {name: "Goodie", secretPrediction: "abc"}, 
             {name: "Baddie", secretPrediction: "def"} 
            ] 
    }
    

    That way it would be possible in a single query to return all the players and only the playerPrediction for the given person.